PageRenderTime 43ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/common/libraries/plugin/pear/phing/listener/XmlLogger.php

https://bitbucket.org/chamilo/chamilo-dev/
PHP | 377 lines | 168 code | 58 blank | 151 comment | 9 complexity | 7347b90ee99cfb7efbfd15542e7ec7d4 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-2.1, LGPL-3.0, GPL-3.0, MIT
  1. <?php
  2. /**
  3. * $Id: XmlLogger.php 552 2009-08-29 12:18:13Z mrook $
  4. *
  5. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  6. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  7. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  8. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  9. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  10. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  11. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  12. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  13. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  14. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  15. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  16. *
  17. * This software consists of voluntary contributions made by many individuals
  18. * and is licensed under the LGPL. For more information please see
  19. * <http://phing.info>.
  20. */
  21. require_once 'phing/BuildLogger.php';
  22. require_once 'phing/listener/DefaultLogger.php';
  23. require_once 'phing/system/util/Timer.php';
  24. /**
  25. * Generates a file in the current directory with
  26. * an XML description of what happened during a build.
  27. * The default filename is "log.xml", but this can be overridden
  28. * with the property <code>XmlLogger.file</code>.
  29. *
  30. * @author Michiel Rook <michiel.rook@gmail.com>
  31. * @version $Id: XmlLogger.php 552 2009-08-29 12:18:13Z mrook $
  32. * @package phing.listener
  33. */
  34. class XmlLogger implements BuildLogger
  35. {
  36. /** XML element name for a build. */
  37. const BUILD_TAG = "build";
  38. /** XML element name for a target. */
  39. const TARGET_TAG = "target";
  40. /** XML element name for a task. */
  41. const TASK_TAG = "task";
  42. /** XML element name for a message. */
  43. const MESSAGE_TAG = "message";
  44. /** XML attribute name for a name. */
  45. const NAME_ATTR = "name";
  46. /** XML attribute name for a time. */
  47. const TIME_ATTR = "time";
  48. /** XML attribute name for a message priority. */
  49. const PRIORITY_ATTR = "priority";
  50. /** XML attribute name for a file location. */
  51. const LOCATION_ATTR = "location";
  52. /** XML attribute name for an error description. */
  53. const ERROR_ATTR = "error";
  54. /** XML element name for a stack trace. */
  55. const STACKTRACE_TAG = "stacktrace";
  56. /**
  57. * @var DOMDocument The XML document created by this logger.
  58. */
  59. private $doc;
  60. /**
  61. * @var int Start time for entire build.
  62. */
  63. private $buildTimerStart = 0;
  64. /**
  65. * @var DOMElement Top-level (root) build element
  66. */
  67. private $buildElement;
  68. /**
  69. * @var array DOMElement[] The parent of the element being processed.
  70. */
  71. private $elementStack = array();
  72. /**
  73. * @var array int[] Array of millisecond times for the various elements being processed.
  74. */
  75. private $timesStack = array();
  76. /**
  77. * @var int
  78. */
  79. private $msgOutputLevel = Project :: MSG_DEBUG;
  80. /**
  81. * @var OutputStream Stream to use for standard output.
  82. */
  83. private $out;
  84. /**
  85. * @var OutputStream Stream to use for error output.
  86. */
  87. private $err;
  88. /**
  89. * @var string Name of filename to create.
  90. */
  91. private $outFilename;
  92. /**
  93. * Constructs a new BuildListener that logs build events to an XML file.
  94. */
  95. public function __construct()
  96. {
  97. $this->doc = new DOMDocument("1.0", "UTF-8");
  98. $this->doc->formatOutput = true;
  99. }
  100. /**
  101. * Fired when the build starts, this builds the top-level element for the
  102. * document and remembers the time of the start of the build.
  103. *
  104. * @param BuildEvent Ignored.
  105. */
  106. function buildStarted(BuildEvent $event)
  107. {
  108. $this->buildTimerStart = Phing :: currentTimeMillis();
  109. $this->buildElement = $this->doc->createElement(XmlLogger :: BUILD_TAG);
  110. array_push($this->elementStack, $this->buildElement);
  111. array_push($this->timesStack, $this->buildTimerStart);
  112. }
  113. /**
  114. * Fired when the build finishes, this adds the time taken and any
  115. * error stacktrace to the build element and writes the document to disk.
  116. *
  117. * @param BuildEvent $event An event with any relevant extra information.
  118. * Will not be <code>null</code>.
  119. */
  120. public function buildFinished(BuildEvent $event)
  121. {
  122. $elapsedTime = Phing :: currentTimeMillis() - $this->buildTimerStart;
  123. $this->buildElement->setAttribute(XmlLogger :: TIME_ATTR, DefaultLogger :: formatTime($elapsedTime));
  124. if ($event->getException() != null)
  125. {
  126. $this->buildElement->setAttribute(XmlLogger :: ERROR_ATTR, $event->getException()->getMessage());
  127. $errText = $this->doc->createCDATASection($event->getException()->getTraceAsString());
  128. $stacktrace = $this->doc->createElement(XmlLogger :: STACKTRACE_TAG);
  129. $stacktrace->appendChild($errText);
  130. $this->buildElement->appendChild($stacktrace);
  131. }
  132. $this->doc->appendChild($this->buildElement);
  133. $outFilename = $event->getProject()->getProperty("XmlLogger.file");
  134. if ($outFilename == null)
  135. {
  136. $outFilename = "log.xml";
  137. }
  138. try
  139. {
  140. $stream = $this->out;
  141. if ($stream === null)
  142. {
  143. $stream = new FileOutputStream($outFilename);
  144. }
  145. // Yes, we could just stream->write() but this will eventually be the better
  146. // way to do this (when we need to worry about charset conversions.
  147. $writer = new OutputStreamWriter($stream);
  148. $writer->write($this->doc->saveXML());
  149. $writer->close();
  150. }
  151. catch (IOException $exc)
  152. {
  153. try
  154. {
  155. $stream->close(); // in case there is a stream open still ...
  156. }
  157. catch (Exception $x)
  158. {
  159. }
  160. throw new BuildException("Unable to write log file.", $exc);
  161. }
  162. // cleanup:remove the buildElement
  163. $this->buildElement = null;
  164. array_pop($this->elementStack);
  165. array_pop($this->timesStack);
  166. }
  167. /**
  168. * Fired when a target starts building, remembers the current time and the name of the target.
  169. *
  170. * @param BuildEvent $event An event with any relevant extra information.
  171. * Will not be <code>null</code>.
  172. */
  173. public function targetStarted(BuildEvent $event)
  174. {
  175. $target = $event->getTarget();
  176. $targetElement = $this->doc->createElement(XmlLogger :: TARGET_TAG);
  177. $targetElement->setAttribute(XmlLogger :: NAME_ATTR, $target->getName());
  178. array_push($this->timesStack, Phing :: currentTimeMillis());
  179. array_push($this->elementStack, $targetElement);
  180. }
  181. /**
  182. * Fired when a target finishes building, this adds the time taken
  183. * to the appropriate target element in the log.
  184. *
  185. * @param BuildEvent $event An event with any relevant extra information.
  186. * Will not be <code>null</code>.
  187. */
  188. public function targetFinished(BuildEvent $event)
  189. {
  190. $targetTimerStart = array_pop($this->timesStack);
  191. $targetElement = array_pop($this->elementStack);
  192. $elapsedTime = Phing :: currentTimeMillis() - $targetTimerStart;
  193. $targetElement->setAttribute(XmlLogger :: TIME_ATTR, DefaultLogger :: formatTime($elapsedTime));
  194. $parentElement = $this->elementStack[count($this->elementStack) - 1];
  195. $parentElement->appendChild($targetElement);
  196. }
  197. /**
  198. * Fired when a task starts building, remembers the current time and the name of the task.
  199. *
  200. * @param BuildEvent $event An event with any relevant extra information.
  201. * Will not be <code>null</code>.
  202. */
  203. public function taskStarted(BuildEvent $event)
  204. {
  205. $task = $event->getTask();
  206. $taskElement = $this->doc->createElement(XmlLogger :: TASK_TAG);
  207. $taskElement->setAttribute(XmlLogger :: NAME_ATTR, $task->getTaskName());
  208. $taskElement->setAttribute(XmlLogger :: LOCATION_ATTR, $task->getLocation()->toString());
  209. array_push($this->timesStack, Phing :: currentTimeMillis());
  210. array_push($this->elementStack, $taskElement);
  211. }
  212. /**
  213. * Fired when a task finishes building, this adds the time taken
  214. * to the appropriate task element in the log.
  215. *
  216. * @param BuildEvent $event An event with any relevant extra information.
  217. * Will not be <code>null</code>.
  218. */
  219. public function taskFinished(BuildEvent $event)
  220. {
  221. $taskTimerStart = array_pop($this->timesStack);
  222. $taskElement = array_pop($this->elementStack);
  223. $elapsedTime = Phing :: currentTimeMillis() - $taskTimerStart;
  224. $taskElement->setAttribute(XmlLogger :: TIME_ATTR, DefaultLogger :: formatTime($elapsedTime));
  225. $parentElement = $this->elementStack[count($this->elementStack) - 1];
  226. $parentElement->appendChild($taskElement);
  227. }
  228. /**
  229. * Fired when a message is logged, this adds a message element to the
  230. * most appropriate parent element (task, target or build) and records
  231. * the priority and text of the message.
  232. *
  233. * @param BuildEvent An event with any relevant extra information.
  234. * Will not be <code>null</code>.
  235. */
  236. public function messageLogged(BuildEvent $event)
  237. {
  238. $priority = $event->getPriority();
  239. if ($priority > $this->msgOutputLevel)
  240. {
  241. return;
  242. }
  243. $messageElement = $this->doc->createElement(XmlLogger :: MESSAGE_TAG);
  244. switch ($priority)
  245. {
  246. case Project :: MSG_ERR :
  247. $name = "error";
  248. break;
  249. case Project :: MSG_WARN :
  250. $name = "warn";
  251. break;
  252. case Project :: MSG_INFO :
  253. $name = "info";
  254. break;
  255. default :
  256. $name = "debug";
  257. break;
  258. }
  259. $messageElement->setAttribute(XmlLogger :: PRIORITY_ATTR, $name);
  260. if (function_exists('mb_convert_encoding'))
  261. {
  262. $messageConverted = mb_convert_encoding($event->getMessage(), 'UTF-8');
  263. }
  264. else
  265. {
  266. $messageConverted = utf8_encode($event->getMessage());
  267. }
  268. $messageText = $this->doc->createCDATASection($messageConverted);
  269. $messageElement->appendChild($messageText);
  270. if (! empty($this->elementStack))
  271. {
  272. $this->elementStack[count($this->elementStack) - 1]->appendChild($messageElement);
  273. }
  274. }
  275. /**
  276. * Set the msgOutputLevel this logger is to respond to.
  277. *
  278. * Only messages with a message level lower than or equal to the given
  279. * level are output to the log.
  280. *
  281. * <p> Constants for the message levels are in Project.php. The order of
  282. * the levels, from least to most verbose, is:
  283. *
  284. * <ul>
  285. * <li>Project::MSG_ERR</li>
  286. * <li>Project::MSG_WARN</li>
  287. * <li>Project::MSG_INFO</li>
  288. * <li>Project::MSG_VERBOSE</li>
  289. * <li>Project::MSG_DEBUG</li>
  290. * </ul>
  291. *
  292. * The default message level for DefaultLogger is Project::MSG_ERR.
  293. *
  294. * @param int $level The logging level for the logger.
  295. * @see BuildLogger#setMessageOutputLevel()
  296. */
  297. public function setMessageOutputLevel($level)
  298. {
  299. $this->msgOutputLevel = (int) $level;
  300. }
  301. /**
  302. * Sets the output stream.
  303. * @param OutputStream $output
  304. * @see BuildLogger#setOutputStream()
  305. */
  306. public function setOutputStream(OutputStream $output)
  307. {
  308. $this->out = $output;
  309. }
  310. /**
  311. * Sets the error stream.
  312. * @param OutputStream $err
  313. * @see BuildLogger#setErrorStream()
  314. */
  315. public function setErrorStream(OutputStream $err)
  316. {
  317. $this->err = $err;
  318. }
  319. }