taskjuggler 3.1.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (410) hide show
  1. data/CHANGELOG +44 -0
  2. data/bin/tj3webd +4 -0
  3. data/data/css/tjreport.css +14 -5
  4. data/data/tjp.vim +22 -7
  5. data/examples/Fedora-20/reports.tji +2 -4
  6. data/examples/Scrum/Product Burndown.csv +26 -0
  7. data/examples/Scrum/Sprint 1 Burndown.csv +26 -0
  8. data/examples/Scrum/Sprint 2 Burndown.csv +26 -0
  9. data/examples/Scrum/Sprint 3 Burndown.csv +26 -0
  10. data/examples/Scrum/scrum.tjp +141 -0
  11. data/examples/Tutorial/tutorial.tjp +13 -7
  12. data/lib/taskjuggler/Attributes.rb +2 -3
  13. data/lib/taskjuggler/HTMLDocument.rb +25 -18
  14. data/lib/taskjuggler/Journal.rb +85 -65
  15. data/lib/taskjuggler/KeywordDocumentation.rb +25 -13
  16. data/lib/taskjuggler/LeaveList.rb +1 -1
  17. data/lib/taskjuggler/Limits.rb +3 -5
  18. data/lib/taskjuggler/MessageHandler.rb +173 -19
  19. data/lib/taskjuggler/Painter.rb +75 -0
  20. data/lib/taskjuggler/Painter/BasicShapes.rb +76 -0
  21. data/lib/taskjuggler/Painter/Color.rb +273 -0
  22. data/lib/taskjuggler/Painter/Element.rb +56 -0
  23. data/lib/taskjuggler/Painter/FontData.rb +221 -0
  24. data/lib/taskjuggler/Painter/FontMetrics.rb +125 -0
  25. data/lib/taskjuggler/Painter/FontMetricsData.rb +151 -0
  26. data/lib/taskjuggler/Painter/Group.rb +77 -0
  27. data/lib/taskjuggler/Painter/Points.rb +47 -0
  28. data/lib/taskjuggler/Painter/Primitives.rb +100 -0
  29. data/lib/taskjuggler/Painter/SVGSupport.rb +36 -0
  30. data/lib/taskjuggler/Painter/Text.rb +36 -0
  31. data/lib/taskjuggler/Project.rb +46 -29
  32. data/lib/taskjuggler/ProjectFileParser.rb +24 -22
  33. data/lib/taskjuggler/ProjectFileScanner.rb +2 -2
  34. data/lib/taskjuggler/PropertyTreeNode.rb +26 -34
  35. data/lib/taskjuggler/Query.rb +8 -5
  36. data/lib/taskjuggler/RealFormat.rb +3 -0
  37. data/lib/taskjuggler/Resource.rb +3 -5
  38. data/lib/taskjuggler/ResourceScenario.rb +19 -7
  39. data/lib/taskjuggler/RichText.rb +4 -6
  40. data/lib/taskjuggler/RichText/FunctionExample.rb +1 -1
  41. data/lib/taskjuggler/RichText/FunctionHandler.rb +5 -6
  42. data/lib/taskjuggler/RichText/Parser.rb +4 -6
  43. data/lib/taskjuggler/RichText/RTFNavigator.rb +1 -1
  44. data/lib/taskjuggler/RichText/RTFQuery.rb +2 -3
  45. data/lib/taskjuggler/RichText/RTFReport.rb +1 -1
  46. data/lib/taskjuggler/RichText/RTFReportLink.rb +1 -2
  47. data/lib/taskjuggler/RichText/RTFWithQuerySupport.rb +1 -1
  48. data/lib/taskjuggler/RichText/Scanner.rb +6 -6
  49. data/lib/taskjuggler/RichText/Snip.rb +1 -2
  50. data/lib/taskjuggler/RuntimeConfig.rb +9 -6
  51. data/lib/taskjuggler/ScenarioData.rb +4 -3
  52. data/lib/taskjuggler/Scoreboard.rb +6 -0
  53. data/lib/taskjuggler/SheetHandlerBase.rb +25 -8
  54. data/lib/taskjuggler/SimpleQueryExpander.rb +14 -5
  55. data/lib/taskjuggler/SyntaxReference.rb +1 -2
  56. data/lib/taskjuggler/TableColumnSorter.rb +84 -0
  57. data/lib/taskjuggler/Task.rb +3 -5
  58. data/lib/taskjuggler/TaskJuggler.rb +36 -29
  59. data/lib/taskjuggler/TaskScenario.rb +154 -66
  60. data/lib/taskjuggler/TextParser.rb +24 -17
  61. data/lib/taskjuggler/TextParser/Scanner.rb +16 -11
  62. data/lib/taskjuggler/TextParser/SourceFileInfo.rb +20 -15
  63. data/lib/taskjuggler/TimeSheets.rb +6 -12
  64. data/lib/taskjuggler/Tj3AppBase.rb +35 -16
  65. data/lib/taskjuggler/Tj3Config.rb +1 -1
  66. data/lib/taskjuggler/TjpSyntaxRules.rb +239 -49
  67. data/lib/taskjuggler/XMLElement.rb +9 -2
  68. data/lib/taskjuggler/apps/Tj3.rb +43 -37
  69. data/lib/taskjuggler/apps/Tj3Client.rb +62 -112
  70. data/lib/taskjuggler/apps/Tj3Daemon.rb +66 -29
  71. data/lib/taskjuggler/apps/Tj3Man.rb +5 -5
  72. data/lib/taskjuggler/apps/Tj3SsReceiver.rb +10 -13
  73. data/lib/taskjuggler/apps/Tj3SsSender.rb +13 -16
  74. data/lib/taskjuggler/apps/Tj3TsReceiver.rb +10 -13
  75. data/lib/taskjuggler/apps/Tj3TsSender.rb +12 -15
  76. data/lib/taskjuggler/apps/Tj3TsSummary.rb +12 -15
  77. data/lib/taskjuggler/apps/Tj3WebD.rb +99 -0
  78. data/lib/taskjuggler/daemon/Daemon.rb +50 -10
  79. data/lib/taskjuggler/daemon/DaemonConnector.rb +127 -0
  80. data/lib/taskjuggler/daemon/ProcessIntercom.rb +36 -21
  81. data/lib/taskjuggler/daemon/ProjectBroker.rb +122 -112
  82. data/lib/taskjuggler/daemon/ProjectServer.rb +78 -46
  83. data/lib/taskjuggler/daemon/ReportServer.rb +52 -28
  84. data/lib/taskjuggler/daemon/ReportServlet.rb +92 -21
  85. data/lib/taskjuggler/daemon/WebServer.rb +75 -22
  86. data/lib/taskjuggler/daemon/WelcomePage.rb +1 -0
  87. data/lib/taskjuggler/reports/AccountListRE.rb +3 -3
  88. data/lib/taskjuggler/reports/CSVFile.rb +9 -2
  89. data/lib/taskjuggler/reports/ChartPlotter.rb +453 -0
  90. data/lib/taskjuggler/reports/Navigator.rb +1 -0
  91. data/lib/taskjuggler/reports/NikuReport.rb +4 -4
  92. data/lib/taskjuggler/reports/Report.rb +6 -18
  93. data/lib/taskjuggler/reports/ReportBase.rb +9 -9
  94. data/lib/taskjuggler/reports/ReportContext.rb +2 -2
  95. data/lib/taskjuggler/reports/StatusSheetReport.rb +6 -6
  96. data/lib/taskjuggler/reports/TableReport.rb +24 -15
  97. data/lib/taskjuggler/reports/TimeSheetReport.rb +5 -5
  98. data/lib/taskjuggler/reports/TraceReport.rb +251 -0
  99. data/lib/tj3webd.rb +17 -0
  100. data/manual/Day_To_Day_Juggling +10 -3
  101. data/manual/Installation +38 -19
  102. data/manual/Software +25 -19
  103. data/manual/Tutorial +119 -110
  104. data/manual/html/Day_To_Day_Juggling.html +7 -5
  105. data/manual/html/Getting_Started.html +4 -4
  106. data/manual/html/How_To_Contribute.html +4 -4
  107. data/manual/html/Installation.html +19 -11
  108. data/manual/html/Intro.html +4 -4
  109. data/manual/html/Reporting_Bugs.html +4 -4
  110. data/manual/html/Rich_Text_Attributes.html +4 -4
  111. data/manual/html/Software.html +15 -11
  112. data/manual/html/TaskJuggler_2x_Migration.html +4 -4
  113. data/manual/html/TaskJuggler_Internals.html +4 -4
  114. data/manual/html/The_TaskJuggler_Syntax.html +4 -4
  115. data/manual/html/Tutorial.html +41 -32
  116. data/manual/html/account.html +4 -4
  117. data/manual/html/account.task.html +4 -4
  118. data/manual/html/accountprefix.html +4 -4
  119. data/manual/html/accountreport.html +27 -9
  120. data/manual/html/accountroot.html +5 -5
  121. data/manual/html/active.html +4 -4
  122. data/manual/html/adopt.task.html +4 -4
  123. data/manual/html/aggregate.html +4 -4
  124. data/manual/html/alert.html +4 -4
  125. data/manual/html/alertlevels.html +4 -4
  126. data/manual/html/allocate.html +5 -5
  127. data/manual/html/alphabet.html +4 -4
  128. data/manual/html/alternative.html +4 -4
  129. data/manual/html/author.html +4 -4
  130. data/manual/html/balance.html +5 -5
  131. data/manual/html/booking.resource.html +4 -4
  132. data/manual/html/booking.task.html +4 -4
  133. data/manual/html/caption.html +5 -5
  134. data/manual/html/cellcolor.column.html +43 -8
  135. data/manual/html/celltext.column.html +4 -4
  136. data/manual/html/center.html +5 -5
  137. data/manual/html/charge.html +4 -4
  138. data/manual/html/chargeset.html +4 -4
  139. data/manual/html/columnid.html +27 -15
  140. data/manual/html/columns.html +5 -5
  141. data/manual/html/complete.html +4 -4
  142. data/manual/html/copyright.html +4 -4
  143. data/manual/html/credits.html +4 -4
  144. data/manual/html/css/tjreport.css +14 -5
  145. data/manual/html/currency.html +4 -4
  146. data/manual/html/currencyformat.html +5 -5
  147. data/manual/html/dailymax.html +5 -5
  148. data/manual/html/dailymin.html +5 -5
  149. data/manual/html/dailyworkinghours.html +4 -4
  150. data/manual/html/date.extend.html +4 -4
  151. data/manual/html/date.html +5 -5
  152. data/manual/html/definitions.html +4 -4
  153. data/manual/html/depends.html +4 -4
  154. data/manual/html/details.html +4 -4
  155. data/manual/html/disabled.html +4 -4
  156. data/manual/html/duration.html +4 -4
  157. data/manual/html/efficiency.html +4 -4
  158. data/manual/html/effort.html +4 -4
  159. data/manual/html/email.html +4 -4
  160. data/manual/html/enabled.html +4 -4
  161. data/manual/html/end.column.html +4 -4
  162. data/manual/html/end.html +4 -4
  163. data/manual/html/end.limit.html +4 -4
  164. data/manual/html/end.report.html +5 -5
  165. data/manual/html/end.timesheet.html +4 -4
  166. data/manual/html/endcredit.html +4 -4
  167. data/manual/html/epilog.html +5 -5
  168. data/manual/html/export.html +4 -4
  169. data/manual/html/extend.html +4 -4
  170. data/manual/html/fail.html +43 -8
  171. data/manual/html/fdl.html +4 -4
  172. data/manual/html/flags.account.html +4 -4
  173. data/manual/html/flags.html +4 -4
  174. data/manual/html/flags.journalentry.html +4 -4
  175. data/manual/html/flags.report.html +5 -5
  176. data/manual/html/flags.resource.html +4 -4
  177. data/manual/html/flags.statussheet.html +4 -4
  178. data/manual/html/flags.task.html +4 -4
  179. data/manual/html/flags.timesheet.html +4 -4
  180. data/manual/html/fontcolor.column.html +43 -8
  181. data/manual/html/footer.html +5 -5
  182. data/manual/html/formats.html +5 -5
  183. data/manual/html/functions.html +4 -4
  184. data/manual/html/gapduration.html +4 -4
  185. data/manual/html/gaplength.html +4 -4
  186. data/manual/html/halign.center.html +4 -4
  187. data/manual/html/halign.column.html +43 -8
  188. data/manual/html/halign.left.html +4 -4
  189. data/manual/html/halign.right.html +4 -4
  190. data/manual/html/hasalert.html +4 -4
  191. data/manual/html/header.html +5 -5
  192. data/manual/html/headline.html +7 -7
  193. data/manual/html/height.html +72 -0
  194. data/manual/html/hideaccount.html +46 -11
  195. data/manual/html/hidejournalentry.html +5 -5
  196. data/manual/html/hidereport.html +43 -8
  197. data/manual/html/hideresource.html +44 -9
  198. data/manual/html/hidetask.html +44 -9
  199. data/manual/html/icalreport.html +4 -4
  200. data/manual/html/include.macro.html +4 -4
  201. data/manual/html/include.project.html +4 -4
  202. data/manual/html/include.properties.html +4 -4
  203. data/manual/html/index.html +2 -1
  204. data/manual/html/inherit.extend.html +4 -4
  205. data/manual/html/interval1.html +4 -4
  206. data/manual/html/interval2.html +4 -4
  207. data/manual/html/interval3.html +4 -4
  208. data/manual/html/interval4.html +4 -4
  209. data/manual/html/isactive.html +4 -4
  210. data/manual/html/ischildof.html +4 -4
  211. data/manual/html/isdependencyof.html +4 -4
  212. data/manual/html/isdutyof.html +4 -4
  213. data/manual/html/isfeatureof.html +4 -4
  214. data/manual/html/isleaf.html +4 -4
  215. data/manual/html/ismilestone.html +4 -4
  216. data/manual/html/isongoing.html +4 -4
  217. data/manual/html/isresource.html +4 -4
  218. data/manual/html/isresponsibilityof.html +4 -4
  219. data/manual/html/istask.html +4 -4
  220. data/manual/html/journalattributes.html +11 -7
  221. data/manual/html/journalentry.html +4 -4
  222. data/manual/html/journalmode.html +5 -5
  223. data/manual/html/leaveallowance.html +5 -5
  224. data/manual/html/leaves.html +5 -6
  225. data/manual/html/left.html +5 -5
  226. data/manual/html/length.html +4 -4
  227. data/manual/html/limits.allocate.html +4 -4
  228. data/manual/html/limits.html +4 -4
  229. data/manual/html/limits.resource.html +4 -4
  230. data/manual/html/limits.task.html +4 -4
  231. data/manual/html/listitem.column.html +4 -4
  232. data/manual/html/listtype.column.html +4 -4
  233. data/manual/html/loadunit.html +5 -5
  234. data/manual/html/logicalexpression.html +8 -44
  235. data/manual/html/logicalflagexpression.html +4 -4
  236. data/manual/html/macro.html +4 -4
  237. data/manual/html/managers.html +4 -4
  238. data/manual/html/mandatory.html +4 -4
  239. data/manual/html/maxend.html +4 -4
  240. data/manual/html/maximum.html +5 -5
  241. data/manual/html/maxstart.html +4 -4
  242. data/manual/html/milestone.html +4 -4
  243. data/manual/html/minend.html +4 -4
  244. data/manual/html/minimum.html +5 -5
  245. data/manual/html/minstart.html +4 -4
  246. data/manual/html/monthlymax.html +5 -5
  247. data/manual/html/monthlymin.html +5 -5
  248. data/manual/html/navbar.html +10 -4
  249. data/manual/html/navigator.html +4 -4
  250. data/manual/html/newtask.html +4 -4
  251. data/manual/html/nikureport.html +4 -4
  252. data/manual/html/note.task.html +4 -4
  253. data/manual/html/now.html +4 -4
  254. data/manual/html/numberformat.html +5 -5
  255. data/manual/html/onend.html +4 -4
  256. data/manual/html/onstart.html +4 -4
  257. data/manual/html/opennodes.html +5 -5
  258. data/manual/html/overtime.booking.html +4 -4
  259. data/manual/html/period.column.html +4 -4
  260. data/manual/html/period.limit.html +4 -4
  261. data/manual/html/period.report.html +5 -5
  262. data/manual/html/period.task.html +4 -4
  263. data/manual/html/persistent.html +4 -4
  264. data/manual/html/precedes.html +4 -4
  265. data/manual/html/priority.html +4 -4
  266. data/manual/html/priority.timesheet.html +4 -4
  267. data/manual/html/project.html +4 -4
  268. data/manual/html/projectid.html +4 -4
  269. data/manual/html/projectid.task.html +4 -4
  270. data/manual/html/projectids.html +4 -4
  271. data/manual/html/projection.html +5 -7
  272. data/manual/html/prolog.html +5 -5
  273. data/manual/html/properties.html +11 -5
  274. data/manual/html/purge.html +5 -5
  275. data/manual/html/rate.html +4 -4
  276. data/manual/html/rate.resource.html +4 -4
  277. data/manual/html/reference.extend.html +4 -4
  278. data/manual/html/remaining.html +4 -4
  279. data/manual/html/replace.html +4 -4
  280. data/manual/html/reportprefix.html +4 -4
  281. data/manual/html/resource.html +4 -10
  282. data/manual/html/resourceattributes.html +4 -4
  283. data/manual/html/resourceprefix.html +4 -4
  284. data/manual/html/resourcereport.html +28 -10
  285. data/manual/html/resourceroot.html +5 -5
  286. data/manual/html/resources.limit.html +4 -4
  287. data/manual/html/responsible.html +4 -4
  288. data/manual/html/richtext.extend.html +4 -4
  289. data/manual/html/right.html +5 -5
  290. data/manual/html/rollupaccount.html +44 -9
  291. data/manual/html/rollupresource.html +44 -9
  292. data/manual/html/rolluptask.html +44 -9
  293. data/manual/html/scale.column.html +4 -4
  294. data/manual/html/scenario.html +4 -22
  295. data/manual/html/scenario.ical.html +4 -4
  296. data/manual/html/scenarios.export.html +4 -4
  297. data/manual/html/scenarios.html +5 -5
  298. data/manual/html/scenariospecific.extend.html +4 -4
  299. data/manual/html/scheduled.html +4 -4
  300. data/manual/html/scheduling.html +4 -4
  301. data/manual/html/select.html +4 -4
  302. data/manual/html/selfcontained.html +5 -5
  303. data/manual/html/shift.allocate.html +4 -4
  304. data/manual/html/shift.html +4 -4
  305. data/manual/html/shift.resource.html +5 -5
  306. data/manual/html/shift.task.html +4 -4
  307. data/manual/html/shift.timesheet.html +4 -4
  308. data/manual/html/shifts.allocate.html +4 -4
  309. data/manual/html/shifts.resource.html +4 -4
  310. data/manual/html/shifts.task.html +4 -4
  311. data/manual/html/shorttimeformat.html +4 -4
  312. data/manual/html/sloppy.booking.html +4 -4
  313. data/manual/html/sloppy.projection.html +5 -5
  314. data/manual/html/sortaccounts.html +5 -5
  315. data/manual/html/sortjournalentries.html +5 -5
  316. data/manual/html/sortresources.html +5 -5
  317. data/manual/html/sorttasks.html +5 -5
  318. data/manual/html/start.column.html +4 -4
  319. data/manual/html/start.html +4 -4
  320. data/manual/html/start.limit.html +4 -4
  321. data/manual/html/start.report.html +5 -5
  322. data/manual/html/startcredit.html +4 -4
  323. data/manual/html/status.statussheet.html +4 -4
  324. data/manual/html/status.timesheet.html +4 -4
  325. data/manual/html/statussheet.html +4 -4
  326. data/manual/html/statussheetreport.html +4 -4
  327. data/manual/html/strict.projection.html +5 -5
  328. data/manual/html/summary.html +4 -4
  329. data/manual/html/supplement.html +4 -4
  330. data/manual/html/supplement.resource.html +4 -10
  331. data/manual/html/supplement.task.html +4 -28
  332. data/manual/html/tagfile.html +4 -4
  333. data/manual/html/task.html +4 -28
  334. data/manual/html/task.statussheet.html +4 -4
  335. data/manual/html/task.timesheet.html +4 -4
  336. data/manual/html/taskattributes.html +4 -4
  337. data/manual/html/taskprefix.html +4 -4
  338. data/manual/html/taskreport.html +28 -10
  339. data/manual/html/taskroot.html +5 -5
  340. data/manual/html/text.extend.html +4 -4
  341. data/manual/html/textreport.html +27 -9
  342. data/manual/html/timeformat.html +5 -5
  343. data/manual/html/timeoff.nikureport.html +4 -4
  344. data/manual/html/timesheet.html +4 -4
  345. data/manual/html/timesheetreport.html +23 -5
  346. data/manual/html/timezone.export.html +4 -4
  347. data/manual/html/timezone.html +4 -4
  348. data/manual/html/timezone.report.html +5 -5
  349. data/manual/html/timezone.shift.html +4 -4
  350. data/manual/html/timingresolution.html +4 -4
  351. data/manual/html/title.column.html +4 -4
  352. data/manual/html/title.html +5 -5
  353. data/manual/html/toc.html +207 -179
  354. data/manual/html/tooltip.column.html +45 -10
  355. data/manual/html/tracereport.html +405 -0
  356. data/manual/html/trackingscenario.html +6 -6
  357. data/manual/html/treelevel.html +4 -4
  358. data/manual/html/vacation.html +4 -4
  359. data/manual/html/vacation.resource.html +4 -4
  360. data/manual/html/vacation.shift.html +4 -4
  361. data/manual/html/warn.html +43 -8
  362. data/manual/html/weeklymax.html +5 -5
  363. data/manual/html/weeklymin.html +5 -5
  364. data/manual/html/weekstartsmonday.html +4 -4
  365. data/manual/html/weekstartssunday.html +6 -6
  366. data/manual/html/width.column.html +6 -6
  367. data/manual/html/width.html +72 -0
  368. data/manual/html/work.html +4 -4
  369. data/manual/html/workinghours.project.html +4 -4
  370. data/manual/html/workinghours.resource.html +4 -4
  371. data/manual/html/workinghours.shift.html +4 -4
  372. data/manual/html/yearlyworkingdays.html +4 -4
  373. data/spec/Color_spec.rb +60 -0
  374. data/spec/ProjectBroker_spec.rb +3 -2
  375. data/spec/StatusSheets_spec.rb +5 -4
  376. data/spec/TableColumnSorter_spec.rb +78 -0
  377. data/spec/TimeSheets_spec.rb +6 -2
  378. data/spec/Tj3Daemon_spec.rb +2 -2
  379. data/spec/TraceReport_spec.rb +117 -0
  380. data/taskjuggler.gemspec +1 -1
  381. data/test/MessageChecker.rb +3 -1
  382. data/test/ReferenceGenerator.rb +1 -1
  383. data/test/TestSuite/CSV-Reports/Leave.tjp +1 -1
  384. data/test/TestSuite/CSV-Reports/refs/resourcereport_with_tasks.csv +3 -0
  385. data/test/TestSuite/CSV-Reports/refs/taskcounter.csv +9 -0
  386. data/test/TestSuite/CSV-Reports/refs/taskreport_with_resources.csv +19 -16
  387. data/test/TestSuite/CSV-Reports/refs/weekly.csv +1 -0
  388. data/test/TestSuite/Export-Reports/refs/LogicalExpression.tjp +14 -2
  389. data/test/TestSuite/Export-Reports/refs/tutorial.tjp +98 -86
  390. data/test/TestSuite/Scheduler/Correct/Leaves.tjp +25 -0
  391. data/test/TestSuite/Syntax/Correct/Leave.tjp +1 -1
  392. data/test/TestSuite/Syntax/Correct/LogicalExpression.tjp +9 -1
  393. data/test/TestSuite/Syntax/Correct/TraceReport.tjp +10 -0
  394. data/test/TestSuite/Syntax/Correct/tutorial.tjp +10 -4
  395. data/test/test_CSV-Reports.rb +3 -3
  396. data/test/test_Export-Reports.rb +91 -86
  397. data/test/test_Journal.rb +15 -12
  398. data/test/test_Limits.rb +3 -3
  399. data/test/test_Project.rb +1 -2
  400. data/test/test_ProjectFileScanner.rb +1 -1
  401. data/test/test_PropertySet.rb +1 -1
  402. data/test/test_Query.rb +5 -6
  403. data/test/test_ReportGenerator.rb +15 -7
  404. data/test/test_RichText.rb +4 -3
  405. data/test/test_Scheduler.rb +19 -7
  406. data/test/test_ShiftAssignments.rb +2 -2
  407. data/test/test_SimpleQueryExpander.rb +29 -2
  408. data/test/test_Syntax.rb +14 -5
  409. metadata +49 -10
  410. data/lib/taskjuggler/LogFile.rb +0 -73
@@ -16,9 +16,8 @@ require 'drb/acl'
16
16
  require 'monitor'
17
17
  require 'taskjuggler/daemon/ProcessIntercom'
18
18
  require 'taskjuggler/daemon/ReportServer'
19
- require 'taskjuggler/LogFile'
19
+ require 'taskjuggler/MessageHandler'
20
20
  require 'taskjuggler/TaskJuggler'
21
- require 'taskjuggler/Log'
22
21
  require 'taskjuggler/TjTime'
23
22
 
24
23
  class TaskJuggler
@@ -79,7 +78,7 @@ class TaskJuggler
79
78
  rd, wr = IO.pipe
80
79
 
81
80
  if (@pid = fork) == -1
82
- @log.fatal('ProjectServer fork failed')
81
+ fatal('ps_fork_failed', 'ProjectServer fork failed')
83
82
  elsif @pid.nil?
84
83
  # This is the child
85
84
  if @logConsole
@@ -91,13 +90,12 @@ class TaskJuggler
91
90
  begin
92
91
  $SAFE = 1
93
92
  DRb.install_acl(ACL.new(%w[ deny all allow 127.0.0.1 ]))
94
- DRb.start_service
95
93
  iFace = ProjectServerIface.new(self)
96
94
  begin
97
95
  @uri = DRb.start_service('druby://127.0.0.1:0', iFace).uri
98
- @log.debug("Project server is listening on #{@uri}")
96
+ debug('', "Project server is listening on #{@uri}")
99
97
  rescue
100
- @log.fatal("ProjectServer can't start DRb: #{$!}")
98
+ error('ps_cannot_start_drb', "ProjectServer can't start DRb: #{$!}")
101
99
  end
102
100
 
103
101
  # Send the URI of the newly started DRb server to the parent process.
@@ -114,12 +112,15 @@ class TaskJuggler
114
112
 
115
113
  # Cleanup the DRb threads
116
114
  DRb.thread.join
117
- @log.debug('Project server terminated')
115
+ debug('', 'Project server terminated')
118
116
  exit 0
119
- rescue
120
- $stderr.print $!.to_s
121
- $stderr.print $!.backtrace.join("\n")
122
- @log.fatal("ProjectServer can't start DRb: #{$!}")
117
+ rescue => exception
118
+ # TjRuntimeError exceptions are simply passed through.
119
+ if exception.is_a?(TjRuntimeError)
120
+ raise TjRuntimeError, $!
121
+ end
122
+
123
+ error('ps_cannot_start_drb', "ProjectServer can't start DRb: #{$!}")
123
124
  end
124
125
  else
125
126
  # This is the parent
@@ -144,28 +145,37 @@ class TaskJuggler
144
145
  @modifiedCheck = TjTime.new
145
146
 
146
147
  updateState(:loading, dirAndFiles, false)
147
- @tj = TaskJuggler.new(true)
148
+ begin
149
+ @tj = TaskJuggler.new
150
+ # Make sure that trace reports get CSV formats included so there
151
+ # reports can be generated on request.
152
+ @tj.generateTraces = true
153
+
154
+ # Parse all project files
155
+ unless @tj.parse(args, true)
156
+ warning('parse_failed', "Parsing of #{args.join(' ')} failed")
157
+ updateState(:failed, nil, false)
158
+ @terminate = true
159
+ return false
160
+ end
148
161
 
149
- # Parse all project files
150
- unless @tj.parse(args, true)
151
- @log.error("Parsing of #{args.join(' ')} failed")
162
+ # Then schedule the project
163
+ unless @tj.schedule
164
+ warning('schedule_failed',
165
+ "Scheduling of project #{@tj.projectId} failed")
166
+ updateState(:failed, @tj.projectId, false)
167
+ @terminate = true
168
+ return false
169
+ end
170
+ rescue TjRuntimeError
152
171
  updateState(:failed, nil, false)
153
172
  @terminate = true
154
173
  return false
155
174
  end
156
175
 
157
- # Then schedule the project
158
- unless @tj.schedule
159
- @log.error("Scheduling of project #{@tj.projectId} failed")
160
- updateState(:failed, @tj.projectId, false)
161
- Log.exit('scheduler')
162
- @terminate = true
163
- return false
164
- end
165
-
166
176
  # Great, everything went fine. We've got a project to work with.
167
177
  updateState(:ready, @tj.projectId, false)
168
- @log.info("Project #{@tj.projectId} loaded")
178
+ debug('', "Project #{@tj.projectId} loaded")
169
179
  restartTimer
170
180
  true
171
181
  end
@@ -201,7 +211,7 @@ class TaskJuggler
201
211
  # find it in the @reportServers list, we create a unique tag to identify
202
212
  # it.
203
213
  tag = rand(99999999999999)
204
- @log.debug("Pushing #{tag} onto report server request queue")
214
+ debug('', "Pushing #{tag} onto report server request queue")
205
215
  @reportServerRequests.push(tag)
206
216
 
207
217
  # Now wait until the new ReportServer shows up in the list.
@@ -216,8 +226,8 @@ class TaskJuggler
216
226
  sleep 0.1 if reportServer.nil?
217
227
  end
218
228
 
219
- @log.debug("Got report server with URI #{reportServer.uri} for " +
220
- "tag #{tag}")
229
+ debug('', "Got report server with URI #{reportServer.uri} for " +
230
+ "tag #{tag}")
221
231
  restartTimer
222
232
  [ reportServer.uri, reportServer.authKey ]
223
233
  end
@@ -249,9 +259,16 @@ class TaskJuggler
249
259
  def updateState(state, filesOrId, modified)
250
260
  begin
251
261
  @daemon = DRbObject.new(nil, @daemonURI) unless @daemon
252
- @daemon.updateState(@daemonAuthKey, @authKey, filesOrId, state, modified)
253
- rescue
254
- @log.fatal("Can't update state with daemon: #{$!}")
262
+ @daemon.updateState(@daemonAuthKey, @authKey, filesOrId, state,
263
+ modified)
264
+ rescue => exception
265
+ # TjRuntimeError exceptions are simply passed through.
266
+ if exception.is_a?(TjRuntimeError)
267
+ raise TjRuntimeError, $!
268
+ end
269
+
270
+ error('cannot_update_daemon_state',
271
+ "Can't update state with daemon: #{$!}")
255
272
  end
256
273
  @stateLock.synchronize do
257
274
  @state = state
@@ -265,6 +282,9 @@ class TaskJuggler
265
282
  Thread.new do
266
283
  begin
267
284
  loop do
285
+ # Exit this thread if the @terminate flag is set.
286
+ break if @terminate
287
+
268
288
  # Was the project data provided during object creation?
269
289
  # Then we load the data here.
270
290
  if @projectData
@@ -280,7 +300,7 @@ class TaskJuggler
280
300
  @stateLock.synchronize { @modifiedCheck = TjTime.new }
281
301
 
282
302
  if @tj.project.inputFiles.modified?
283
- @log.info("Project #{@tj.projectId} has been modified")
303
+ debug('', "Project #{@tj.projectId} has been modified")
284
304
  updateState(:ready, @tj.projectId, true)
285
305
  end
286
306
  end
@@ -288,17 +308,17 @@ class TaskJuggler
288
308
  # Check for pending requests for new ReportServers.
289
309
  unless @reportServerRequests.empty?
290
310
  tag = @reportServerRequests.pop
291
- @log.debug("Popped #{tag}")
311
+ debug('', "Popped #{tag}")
292
312
  # Create an new entry for the @reportServers list.
293
313
  rsr = ReportServerRecord.new(tag)
294
- @log.debug("RSR created")
314
+ debug('', "RSR created")
295
315
  # Create a new ReportServer object that runs as a separate
296
316
  # process. The constructor will tell us the URI and authentication
297
317
  # key of the new ReportServer.
298
318
  rs = ReportServer.new(@tj, @logConsole)
299
319
  rsr.uri = rs.uri
300
320
  rsr.authKey = rs.authKey
301
- @log.debug("Adding ReportServer with URI #{rsr.uri} to list")
321
+ debug('', "Adding ReportServer with URI #{rsr.uri} to list")
302
322
  # Add the new ReportServer to our list.
303
323
  @reportServers.synchronize do
304
324
  @reportServers << rsr
@@ -309,25 +329,31 @@ class TaskJuggler
309
329
  # can die during the transaction, the server might hang in some
310
330
  # states. Here we define timeout for each state. If the timeout is
311
331
  # not 0 and exceeded, we immediately terminate the process.
312
- timeouts = { :new => 10, :loading => 15 * 60, :failed => 60,
332
+ timeouts = { :new => 30, :loading => 15 * 60, :failed => 60,
313
333
  :ready => 0 }
314
334
  if timeouts[@state] > 0 &&
315
335
  TjTime.new - @stateUpdated > timeouts[@state]
316
- @log.fatal("Reached timeout for state #{@state}. Terminating.")
336
+ error('state_timeout',
337
+ "Reached timeout for state #{@state}. Terminating.")
317
338
  end
318
339
 
319
340
  # If we have not received a ping from the ProjectBroker for 2
320
341
  # minutes, we assume it has died and terminate as well.
321
342
  if TjTime.new - @lastPing > 180
322
- @log.fatal('Heartbeat from daemon lost. Terminating.')
343
+ error('daemon_heartbeat_lost',
344
+ 'Heartbeat from daemon lost. Terminating.')
323
345
  end
324
346
  sleep 1
325
347
  end
326
- rescue
348
+ rescue => exception
349
+ # TjRuntimeError exceptions are simply passed through.
350
+ if exception.is_a?(TjRuntimeError)
351
+ raise TjRuntimeError, $!
352
+ end
353
+
327
354
  # Make sure we get a backtrace for this thread.
328
- $stderr.print $!.to_s
329
- $stderr.print $!.backtrace.join("\n")
330
- @log.fatal("ProjectServer housekeeping error: #{$!}")
355
+ fatal('ps_housekeeping_error',
356
+ "ProjectServer housekeeping error: #{$!}")
331
357
  end
332
358
  end
333
359
  end
@@ -381,6 +407,8 @@ class TaskJuggler
381
407
  # the ProjectServer.
382
408
  class ReportServerRecord
383
409
 
410
+ include MessageHandler
411
+
384
412
  attr_reader :tag
385
413
  attr_accessor :uri, :authKey
386
414
 
@@ -393,7 +421,6 @@ class TaskJuggler
393
421
  @authKey = nil
394
422
  # The DRbObject of the ReportServer.
395
423
  @reportServer = nil
396
- @log = LogFile.instance
397
424
  end
398
425
 
399
426
  # Send a ping to the ReportServer process to check that it is still
@@ -402,14 +429,19 @@ class TaskJuggler
402
429
  def ping
403
430
  return true unless @uri
404
431
 
405
- @log.debug("Sending ping to ReportServer #{@uri}")
432
+ debug('', "Sending ping to ReportServer #{@uri}")
406
433
  begin
407
434
  @reportServer = DRbObject.new(nil, @uri) unless @reportServer
408
435
  @reportServer.ping(@authKey)
409
- rescue
436
+ rescue => exception
437
+ # TjRuntimeError exceptions are simply passed through.
438
+ if exception.is_a?(TjRuntimeError)
439
+ raise TjRuntimeError, $!
440
+ end
441
+
410
442
  # ReportServer processes terminate on request of their clients. Not
411
443
  # responding to a ping is a normal event.
412
- @log.debug("ReportServer (#{@uri}) has terminated")
444
+ debug('', "ReportServer (#{@uri}) has terminated")
413
445
  return false
414
446
  end
415
447
  true
@@ -43,7 +43,7 @@ class TaskJuggler
43
43
  rd, wr = IO.pipe
44
44
 
45
45
  if (@pid = fork) == -1
46
- @log.fatal('ReportServer fork failed')
46
+ fatal('rs_fork_failed', 'ReportServer fork failed')
47
47
  elsif @pid.nil?
48
48
  if logConsole
49
49
  # If the Broker wasn't daemonized, log stdout and stderr to PID
@@ -56,13 +56,13 @@ class TaskJuggler
56
56
  $SAFE = 1
57
57
  DRb.install_acl(ACL.new(%w[ deny all
58
58
  allow 127.0.0.1 ]))
59
- DRb.start_service
60
59
  iFace = ReportServerIface.new(self)
61
60
  begin
62
61
  uri = DRb.start_service('druby://127.0.0.1:0', iFace).uri
63
- @log.debug("Report server is listening on #{uri}")
62
+ debug('', "Report server is listening on #{uri}")
64
63
  rescue
65
- @log.fatal("ReportServer can't start DRb: #{$!}")
64
+ error('rs_cannot_start_drb',
65
+ "ReportServer can't start DRb: #{$!}")
66
66
  end
67
67
 
68
68
  # Send the URI of the newly started DRb server to the parent process.
@@ -77,12 +77,16 @@ class TaskJuggler
77
77
 
78
78
  # Cleanup the DRb threads
79
79
  DRb.thread.join
80
- @log.debug('Report server terminated')
80
+ debug('', 'Report server terminated')
81
81
  exit 0
82
- rescue
83
- $stderr.print $!.to_s
84
- $stderr.print $!.backtrace.join("\n")
85
- @log.fatal("ReportServer caught unexpected exception: #{$!}")
82
+ rescue => exception
83
+ # TjRuntimeError exceptions are simply passed through.
84
+ if exception.is_a?(TjRuntimeError)
85
+ raise TjRuntimeError, $!
86
+ end
87
+
88
+ error('rs_unexp_excp',
89
+ "ReportServer caught unexpected exception: #{$!}")
86
90
  end
87
91
  else
88
92
  Process.detach(@pid)
@@ -100,7 +104,7 @@ class TaskJuggler
100
104
  def addFile(file)
101
105
  begin
102
106
  @tj.parseFile(file, :reportPropertiesFile)
103
- rescue TjException
107
+ rescue TjRuntimeError
104
108
  return false
105
109
  end
106
110
  restartTimer
@@ -108,40 +112,58 @@ class TaskJuggler
108
112
  end
109
113
 
110
114
  def generateReport(id, regExpMode, formats, dynamicAttributes)
111
- @log.info("Generating report #{id}")
115
+ info('generating_report', "Generating report #{id}")
112
116
  startTime = Time.now
113
- if (ok = @tj.generateReport(id, regExpMode, formats, dynamicAttributes))
114
- @log.info("Report #{id} generated in #{Time.now - startTime} seconds")
115
- else
116
- @log.error("Report generation of #{id} failed")
117
+ begin
118
+ if (ok = @tj.generateReport(id, regExpMode, formats, dynamicAttributes))
119
+ info('report_id_generated',
120
+ "Report #{id} generated in #{Time.now - startTime} seconds")
121
+ else
122
+ error('report_generation_failed', "Report generation of #{id} failed")
123
+ end
124
+ rescue TjRuntimeError
125
+ return false
117
126
  end
118
127
  restartTimer
119
128
  ok
120
129
  end
121
130
 
122
131
  def listReports(id, regExpMode)
123
- @log.info("Listing report #{id}")
124
- if (ok = @tj.listReports(id, regExpMode))
125
- @log.debug("Report list for #{id} generated")
126
- else
127
- @log.error("Report list compilation of #{id} failed")
132
+ info('listing_report_id', "Listing report #{id}")
133
+ begin
134
+ if (ok = @tj.listReports(id, regExpMode))
135
+ debug('', "Report list for #{id} generated")
136
+ else
137
+ error('repor_list_comp_failed',
138
+ "Report list compilation of #{id} failed")
139
+ end
140
+ rescue TjRuntimeError
141
+ return false
128
142
  end
129
143
  restartTimer
130
144
  ok
131
145
  end
132
146
 
133
147
  def checkTimeSheet(sheet)
134
- @log.info("Checking time sheet #{sheet}")
135
- ok = @tj.checkTimeSheet(sheet)
136
- @log.debug("Time sheet #{sheet} is #{ok ? '' : 'not '}ok")
148
+ info('check_time_sheet', "Checking time sheet #{sheet}")
149
+ begin
150
+ ok = @tj.checkTimeSheet(sheet)
151
+ debug('', "Time sheet #{sheet} is #{ok ? '' : 'not '}ok")
152
+ rescue TjRuntimeError
153
+ return false
154
+ end
137
155
  restartTimer
138
156
  ok
139
157
  end
140
158
 
141
159
  def checkStatusSheet(sheet)
142
- @log.info("Checking status sheet #{sheet}")
143
- ok = @tj.checkStatusSheet(sheet)
144
- @log.debug("Status sheet #{sheet} is #{ok ? '' : 'not '}ok")
160
+ info('check_status_sheet', "Checking status sheet #{sheet}")
161
+ begin
162
+ ok = @tj.checkStatusSheet(sheet)
163
+ debug('', "Status sheet #{sheet} is #{ok ? '' : 'not '}ok")
164
+ rescue TjRuntimeError
165
+ return false
166
+ end
145
167
  restartTimer
146
168
  ok
147
169
  end
@@ -152,7 +174,8 @@ class TaskJuggler
152
174
  Thread.new do
153
175
  loop do
154
176
  if TjTime.new - @lastPing > 120
155
- @log.fatal('Heartbeat from ProjectServer lost. Terminating.')
177
+ error('ps_heartbeat_lost',
178
+ 'Heartbeat from ProjectServer lost. Terminating.')
156
179
  end
157
180
  sleep 30
158
181
  end
@@ -181,7 +204,8 @@ class TaskJuggler
181
204
  trap { @server.addFile(file) }
182
205
  end
183
206
 
184
- def generateReport(authKey, reportId, regExpMode, formats, dynamicAttributes)
207
+ def generateReport(authKey, reportId, regExpMode, formats,
208
+ dynamicAttributes)
185
209
  return false unless @server.checkKey(authKey, 'generateReport')
186
210
 
187
211
  trap do
@@ -12,29 +12,43 @@
12
12
  #
13
13
 
14
14
  require 'webrick'
15
+ require 'taskjuggler/MessageHandler'
16
+ require 'taskjuggler/RichText'
17
+ require 'taskjuggler/HTMLDocument'
18
+ require 'taskjuggler/daemon/DaemonConnector'
15
19
 
16
20
  class TaskJuggler
17
21
 
18
22
  class ReportServlet < WEBrick::HTTPServlet::AbstractServlet
19
23
 
20
- def initialize(config, *options)
24
+ def initialize(config, options)
21
25
  super
22
- @broker = options[0]
26
+ @authKey = options[0]
27
+ @host = options[1]
28
+ @port = options[2]
29
+ @uri = options[3]
23
30
  end
24
31
 
25
32
  def self.get_instance(config, options)
26
- self.new(config, *options)
33
+ self.new(config, options)
27
34
  end
28
35
 
29
36
  def do_GET(req, res)
37
+ debug('', "Serving URL #{req}")
30
38
  @req = req
31
39
  @res = res
32
40
  begin
33
- projectId = req.query['project']
34
- reportId = req.query['report']
35
- if projectId.nil? || reportId.nil?
41
+ # WEBrick is returning the query elements as FormData objects. We must
42
+ # use to_s to explicitely convert them to String objects.
43
+ projectId = req.query['project'].to_s
44
+ debug('', "Project ID: #{projectId}")
45
+ reportId = req.query['report'].to_s
46
+ debug('', "Report ID: #{reportId}")
47
+ if projectId.empty? || reportId.empty?
48
+ debug('', "Project welcome page requested")
36
49
  generateWelcomePage(projectId)
37
50
  else
51
+ debug('', "Report #{reportId} of project #{projectId} requested")
38
52
  attributes = req.query['attributes'] || ''
39
53
  attributes = URLParameter.decode(attributes) unless attributes.empty?
40
54
  generateReport(projectId, reportId, attributes)
@@ -45,11 +59,32 @@ class TaskJuggler
45
59
 
46
60
  private
47
61
 
62
+ def connectToBroker
63
+ begin
64
+ broker = DaemonConnector.new(@authKey, @host, @port, @uri)
65
+ rescue
66
+ error('cannot_connect_broker',
67
+ "Cannot connect to the TaskJuggler daemon: #{$!}\n" +
68
+ "Please make sure you have tj3d running and listening " +
69
+ "on port #{@port} or URI '#{@uri}'.")
70
+ end
71
+
72
+ broker
73
+ end
74
+
48
75
  def generateReport(projectId, reportId, attributes)
76
+ broker = connectToBroker
77
+
49
78
  # Request the Project credentials from the ProbjectBroker.
50
- @ps_uri, @ps_authKey = @broker.getProject(projectId)
79
+ begin
80
+ @ps_uri, @ps_authKey = broker.getProject(projectId)
81
+ rescue
82
+ error('cannot_get_project_server',
83
+ "Cannot get project server for ID #{projectId}: #{$!}")
84
+ end
85
+
51
86
  if @ps_uri.nil?
52
- error("No project with ID #{projectId} loaded")
87
+ error('ps_uri_nil', "No project with ID #{projectId} loaded")
53
88
  end
54
89
  # Get the responsible ReportServer that can generate the report.
55
90
  begin
@@ -57,7 +92,8 @@ class TaskJuggler
57
92
  @rs_uri, @rs_authKey = @projectServer.getReportServer(@ps_authKey)
58
93
  @reportServer = DRbObject.new(nil, @rs_uri)
59
94
  rescue
60
- error("Cannot get report server")
95
+ error('cannot_get_report_server',
96
+ "Cannot get report server: #{$!}")
61
97
  end
62
98
  # Create two StringIO buffers that will receive the $stdout and $stderr
63
99
  # text from the report server. This buffer will contain the generated
@@ -70,8 +106,13 @@ class TaskJuggler
70
106
 
71
107
  begin
72
108
  @reportServer.connect(@rs_authKey, stdOut, stdErr, $stdin, true)
73
- rescue
74
- error("Can't connect IO: #{$!}")
109
+ rescue => exception
110
+ # TjRuntimeError exceptions are simply passed through.
111
+ if exception.is_a?(TjRuntimeError)
112
+ raise TjRuntimeError, $!
113
+ end
114
+
115
+ error('rs_io_connect_failed', "Can't connect IO: #{$!}")
75
116
  end
76
117
 
77
118
  # Ask the ReportServer to generate the reports with the provided ID.
@@ -81,21 +122,24 @@ class TaskJuggler
81
122
  rescue
82
123
  stdOut.rewind
83
124
  stdErr.rewind
84
- error("Report server crashed: #{$!}\n#{stdErr.read}\n#{stdOut.read}")
125
+ error('rs_generate_report_failed',
126
+ "Report server crashed: #{$!}\n#{stdErr.read}\n#{stdOut.read}")
85
127
  end
86
128
  # Disconnect the ReportServer
87
129
  begin
88
130
  @reportServer.disconnect(@rs_authKey)
89
131
  rescue
90
- error("Can't disconnect IO: #{$!}")
132
+ error('rs_io_disconnect_failed', "Can't disconnect IO: #{$!}")
91
133
  end
92
134
  # And send a termination request.
93
135
  begin
94
136
  @reportServer.terminate(@rs_authKey)
95
137
  rescue
96
- error("Report server termination failed: #{$!}")
138
+ error('report_server_term_failed',
139
+ "Report server termination failed: #{$!}")
97
140
  end
98
141
  @reportServer = nil
142
+ broker.disconnect
99
143
 
100
144
  @res['content-type'] = 'text/html'
101
145
  stdErr.rewind
@@ -107,7 +151,14 @@ class TaskJuggler
107
151
  end
108
152
 
109
153
  def generateWelcomePage(projectId)
110
- projects = @broker.getProjectList
154
+ broker = connectToBroker
155
+
156
+ begin
157
+ projects = broker.getProjectList
158
+ rescue
159
+ error('cannot_get_project_list',
160
+ "Cannot get project list from daemon: #{$!}")
161
+ end
111
162
 
112
163
  text = "== Welcome to the TaskJuggler Project Server ==\n----\n"
113
164
  projects.each do |id|
@@ -128,6 +179,10 @@ class TaskJuggler
128
179
  text << "* [/taskjuggler?project=#{id} #{getProjectName(id)}]\n"
129
180
  end
130
181
  end
182
+
183
+ # We no longer need the broker.
184
+ broker.disconnect
185
+
131
186
  rt = RichText.new(text)
132
187
  rti = rt.generateIntermediateFormat
133
188
  rti.sectionNumbers = false
@@ -139,26 +194,42 @@ class TaskJuggler
139
194
  end
140
195
 
141
196
  def getProjectName(id)
142
- uri, authKey = @broker.getProject(id)
197
+ broker = connectToBroker
198
+
199
+ uri, authKey = broker.getProject(id)
143
200
  return nil unless uri
144
201
  projectServer = DRbObject.new(nil, uri)
145
202
  return nil unless projectServer
146
- projectServer.getProjectName(authKey)
203
+ res = projectServer.getProjectName(authKey)
204
+
205
+ broker.disconnect
206
+
207
+ res
147
208
  end
148
209
 
149
210
  def getReportList(id)
150
- uri, authKey = @broker.getProject(id)
211
+ broker = connectToBroker
212
+
213
+ uri, authKey = broker.getProject(id)
151
214
  return [] unless uri
152
215
  projectServer = DRbObject.new(nil, uri)
153
216
  return [] unless projectServer
154
- projectServer.getReportList(authKey)
217
+ res = projectServer.getReportList(authKey)
218
+
219
+ broker.disconnect
220
+
221
+ res
155
222
  end
156
223
 
157
- def error(message)
224
+ def error(id, message)
158
225
  @res.status = 412
159
226
  @res.body = "ERROR: #{message}"
160
227
  @res['content-type'] = 'text/plain'
161
- raise "Error: #{message}"
228
+ MessageHandlerInstance.instance.error(id, message)
229
+ end
230
+
231
+ def debug(id, message)
232
+ MessageHandlerInstance.instance.debug(id, message)
162
233
  end
163
234
 
164
235
  end