taskjuggler 3.1.0 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
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