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
@@ -71,17 +71,17 @@ EOT
71
71
  else
72
72
  requestedKeywords.each do |keyword|
73
73
  if (kws = @keywords[keyword, true]).nil?
74
- $stderr.puts "No matches found for '#{keyword}'"
75
- exit 1
74
+ error('tj3man_no_matches', "No matches found for '#{keyword}'")
76
75
  elsif kws.length == 1 || kws.include?(keyword)
77
76
  showManual(keyword)
78
77
  else
79
- $stderr.puts "Multiple matches found for '#{keyword}':\n" +
80
- "#{kws.join(', ')}"
81
- return 1
78
+ warning('tj3man_multi_match',
79
+ "Multiple matches found for '#{keyword}':\n" +
80
+ "#{kws.join(', ')}")
82
81
  end
83
82
  end
84
83
  end
84
+
85
85
  0
86
86
  end
87
87
 
@@ -38,19 +38,16 @@ EOT
38
38
  end
39
39
 
40
40
  def appMain(argv)
41
- begin
42
- ts = TaskJuggler::StatusSheetReceiver.new('tj3ss_receiver')
43
- @rc.configure(ts, 'global')
44
- @rc.configure(ts, 'statussheets')
45
- @rc.configure(ts, 'statussheets.receiver')
46
- ts.workingDir = @workingDir if @workingDir
47
- ts.dryRun = @dryRun
48
-
49
- ts.processEmail
50
- return 0
51
- rescue TjRuntimeError
52
- return 1
53
- end
41
+ ts = TaskJuggler::StatusSheetReceiver.new('tj3ss_receiver')
42
+ @rc.configure(ts, 'global')
43
+ @rc.configure(ts, 'statussheets')
44
+ @rc.configure(ts, 'statussheets.receiver')
45
+ ts.workingDir = @workingDir if @workingDir
46
+ ts.dryRun = @dryRun
47
+
48
+ ts.processEmail
49
+
50
+ 0
54
51
  end
55
52
 
56
53
  end
@@ -68,23 +68,20 @@ EOT
68
68
  end
69
69
 
70
70
  def appMain(argv)
71
- begin
72
- ts = StatusSheetSender.new('tj3ss_sender')
73
- @rc.configure(ts, 'global')
74
- @rc.configure(ts, 'statussheets')
75
- @rc.configure(ts, 'statussheets.sender')
76
- ts.workingDir = @workingDir if @workingDir
77
- ts.dryRun = @dryRun
78
- ts.force = @force
79
- ts.intervalDuration = @intervalDuration if @intervalDuration
80
- ts.date = @date if @date
81
- ts.hideResource = @hideResource if @hideResource
71
+ ts = StatusSheetSender.new('tj3ss_sender')
72
+ @rc.configure(ts, 'global')
73
+ @rc.configure(ts, 'statussheets')
74
+ @rc.configure(ts, 'statussheets.sender')
75
+ ts.workingDir = @workingDir if @workingDir
76
+ ts.dryRun = @dryRun
77
+ ts.force = @force
78
+ ts.intervalDuration = @intervalDuration if @intervalDuration
79
+ ts.date = @date if @date
80
+ ts.hideResource = @hideResource if @hideResource
82
81
 
83
- ts.sendTemplates(@resourceList)
84
- return 0
85
- rescue TjRuntimeError
86
- return 1
87
- end
82
+ ts.sendTemplates(@resourceList)
83
+
84
+ 0
88
85
  end
89
86
 
90
87
  end
@@ -41,19 +41,16 @@ EOT
41
41
  end
42
42
 
43
43
  def appMain(argv)
44
- begin
45
- ts = TimeSheetReceiver.new('tj3ts_receiver')
46
- @rc.configure(ts, 'global')
47
- @rc.configure(ts, 'timesheets')
48
- @rc.configure(ts, 'timesheets.receiver')
49
- ts.workingDir = @workingDir if @workingDir
50
- ts.dryRun = @dryRun
51
-
52
- ts.processEmail
53
- return 0
54
- rescue TjRuntimeError
55
- return 1
56
- end
44
+ ts = TimeSheetReceiver.new('tj3ts_receiver')
45
+ @rc.configure(ts, 'global')
46
+ @rc.configure(ts, 'timesheets')
47
+ @rc.configure(ts, 'timesheets.receiver')
48
+ ts.workingDir = @workingDir if @workingDir
49
+ ts.dryRun = @dryRun
50
+
51
+ ts.processEmail
52
+
53
+ 0
57
54
  end
58
55
 
59
56
  end
@@ -56,22 +56,19 @@ EOT
56
56
  end
57
57
 
58
58
  def appMain(argv)
59
- begin
60
- ts = TimeSheetSender.new('tj3ts_sender')
61
- @rc.configure(ts, 'global')
62
- @rc.configure(ts, 'timesheets')
63
- @rc.configure(ts, 'timesheets.sender')
64
- ts.workingDir = @workingDir if @workingDir
65
- ts.dryRun = @dryRun
66
- ts.force = @force
67
- ts.intervalDuration = @intervalDuration if @intervalDuration
68
- ts.date = @date if @date
59
+ ts = TimeSheetSender.new('tj3ts_sender')
60
+ @rc.configure(ts, 'global')
61
+ @rc.configure(ts, 'timesheets')
62
+ @rc.configure(ts, 'timesheets.sender')
63
+ ts.workingDir = @workingDir if @workingDir
64
+ ts.dryRun = @dryRun
65
+ ts.force = @force
66
+ ts.intervalDuration = @intervalDuration if @intervalDuration
67
+ ts.date = @date if @date
69
68
 
70
- ts.sendTemplates(@resourceList)
71
- return 0
72
- rescue
73
- return 1
74
- end
69
+ ts.sendTemplates(@resourceList)
70
+
71
+ 0
75
72
  end
76
73
 
77
74
  end
@@ -65,22 +65,19 @@ EOT
65
65
  end
66
66
 
67
67
  def appMain(argv)
68
- begin
69
- ts = TimeSheetSummary.new
70
- @rc.configure(ts, 'global')
71
- @rc.configure(ts, 'timesheets')
72
- @rc.configure(ts, 'timesheets.summary')
73
- ts.workingDir = @workingDir if @workingDir
74
- ts.dryRun = @dryRun
75
- ts.date = @date if @date
76
- ts.sheetRecipients += @sheetRecipients
77
- ts.digestRecipients += @digestRecipients
68
+ ts = TimeSheetSummary.new
69
+ @rc.configure(ts, 'global')
70
+ @rc.configure(ts, 'timesheets')
71
+ @rc.configure(ts, 'timesheets.summary')
72
+ ts.workingDir = @workingDir if @workingDir
73
+ ts.dryRun = @dryRun
74
+ ts.date = @date if @date
75
+ ts.sheetRecipients += @sheetRecipients
76
+ ts.digestRecipients += @digestRecipients
78
77
 
79
- ts.sendSummary(@resourceList)
80
- return 0
81
- rescue TjRuntimeError
82
- return 1
83
- end
78
+ ts.sendSummary(@resourceList)
79
+
80
+ 0
84
81
  end
85
82
 
86
83
  end
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env ruby -w
2
+ # encoding: UTF-8
3
+ #
4
+ # = Tj3Daemon.rb -- The TaskJuggler III Project Management Software
5
+ #
6
+ # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012
7
+ # by Chris Schlaeger <chris@linux.com>
8
+ #
9
+ # This program is free software; you can redistribute it and/or modify
10
+ # it under the terms of version 2 of the GNU General Public License as
11
+ # published by the Free Software Foundation.
12
+ #
13
+
14
+ require 'drb'
15
+ require 'taskjuggler/Tj3AppBase'
16
+ require 'taskjuggler/MessageHandler'
17
+ require 'taskjuggler/daemon/WebServer'
18
+
19
+ # Name of the application
20
+ AppConfig.appName = 'tj3webd'
21
+
22
+ class TaskJuggler
23
+
24
+ class Tj3WebD < Tj3AppBase
25
+
26
+ def initialize
27
+ super
28
+
29
+ @mhi = MessageHandlerInstance.instance
30
+ @mhi.logFile = File.join(Dir.getwd, "/#{AppConfig.appName}.log")
31
+ @mhi.appName = AppConfig.appName
32
+ # By default show only warnings and more serious messages.
33
+ @mhi.outputLevel = :warning
34
+ @daemonize = true
35
+ @uriFile = File.join(Dir.getwd, '.tj3d.uri')
36
+ @port = nil
37
+ @webServerPort = nil
38
+ @pidFile = nil
39
+ end
40
+
41
+ def processArguments(argv)
42
+ super do
43
+ @opts.banner += <<'EOT'
44
+ The TaskJuggler web server can be used to serve the HTTP reports of
45
+ TaskJuggler projects to be viewed by any HTML5 compliant web browser. It uses
46
+ the TaskJuggler daemon (tj3d) for data hosting and report generation.
47
+ EOT
48
+ @opts.on('-d', '--dont-daemonize',
49
+ format("Don't put program into daemon mode. Keep it " +
50
+ 'connected to the terminal and show debug output.')) do
51
+ @daemonize = false
52
+ end
53
+ @opts.on('-p', '--port <NUMBER>', Integer,
54
+ format('Use the specified TCP/IP port to connect to the ' +
55
+ 'TaskJuggler daemon (Default: 8474).')) do |arg|
56
+ @port = arg
57
+ end
58
+ @opts.on('--pidfile <FILE NAME>', String,
59
+ format('Write the process ID of the daemon to the ' +
60
+ 'specified file.')) do |arg|
61
+ @pidFile = arg
62
+ end
63
+ @opts.on('--urifile', String,
64
+ format('If the port is 0, use this file to read the URI ' +
65
+ 'of the TaskJuggler daemon.')) do |arg|
66
+ @uriFile = arg
67
+ end
68
+ @opts.on('--webserver-port <NUMBER>', Integer,
69
+ format('Use the specified TCP/IP port to serve web browser ' +
70
+ 'requests (Default: 8080).')) do |arg|
71
+ @webServerPort = arg
72
+ end
73
+ end
74
+ end
75
+
76
+ def appMain(files)
77
+ @rc.configure(self, 'global')
78
+ @rc.configure(@mhi, 'global.log')
79
+ webServer = WebServer.new
80
+ @rc.configure(webServer, 'global')
81
+ @rc.configure(webServer, 'webd')
82
+
83
+ # Set some config variables if corresponding data was provided via the
84
+ # command line.
85
+ webServer.port = @port if @port
86
+ webServer.uriFile = @uriFile.untaint
87
+ webServer.webServerPort = @webServerPort if @webServerPort
88
+ webServer.daemonize = @daemonize
89
+ webServer.pidFile = @pidFile
90
+ debug('', "pidFile 1: #{@pidFile}")
91
+
92
+ webServer.start
93
+ 0
94
+ end
95
+
96
+ end
97
+
98
+ end
99
+
@@ -11,7 +11,7 @@
11
11
  # published by the Free Software Foundation.
12
12
  #
13
13
 
14
- require 'taskjuggler/LogFile'
14
+ require 'taskjuggler/MessageHandler'
15
15
 
16
16
  class TaskJuggler
17
17
 
@@ -20,27 +20,29 @@ class TaskJuggler
20
20
  # this class and call the start() method.
21
21
  class Daemon
22
22
 
23
- attr_accessor :daemonize
24
- attr_reader :log
23
+ include MessageHandler
24
+
25
+ attr_accessor :pidFile, :daemonize
25
26
 
26
27
  def initialize
27
28
  # You can set this flag to false to prevent the program from
28
29
  # disconnecting from the current terminal. This is useful for debugging
29
30
  # purposes.
30
31
  @daemonize = true
31
- @log = LogFile.instance
32
+ # Save the PID of the running daemon as number into this file.
33
+ @pidFile = nil
32
34
  end
33
35
 
34
36
  # Call this method to turn the process into a background process.
35
37
  def start
36
- return unless @daemonize
38
+ return 0 unless @daemonize
37
39
 
38
40
  # Fork and have the parent exit
39
41
  if (pid = fork) == -1
40
- @log.fatal('First fork failed')
42
+ fatal('first_fork_failed', 'First fork failed')
41
43
  elsif !pid.nil?
42
44
  # This is the parent. We can exit now.
43
- @log.debug("Forked a child process with PID #{pid}")
45
+ debug('', "Forked a child process with PID #{pid}")
44
46
  exit! 0
45
47
  end
46
48
 
@@ -48,15 +50,17 @@ class TaskJuggler
48
50
  Process.setsid
49
51
  # Fork again to make sure we lose the controlling terminal
50
52
  if (pid = fork) == -1
51
- @log.fatal('Second fork failed')
53
+ fatal('second_fork_failed', 'Second fork failed')
52
54
  elsif !pid.nil?
53
55
  # This is the parent. We can exit now.
54
- @log.debug("Forked a child process with PID #{pid}")
56
+ debug('', "Forked a child process with PID #{pid}")
55
57
  exit! 0
56
58
  end
57
59
 
58
60
  @pid = Process.pid
59
61
 
62
+ writePidFile
63
+
60
64
  # Change current working directory to the file system root
61
65
  Dir.chdir '/'
62
66
  # Make sure we can create files with any permission
@@ -67,13 +71,49 @@ class TaskJuggler
67
71
  $stdout.reopen('/dev/null', 'a')
68
72
  $stderr.reopen($stdout)
69
73
 
70
- @log.info("The process is running as daemon now with PID #{@pid}")
74
+ info('daemon_pid',
75
+ "The process is running as daemon now with PID #{@pid}")
76
+
71
77
  0
72
78
  end
73
79
 
74
80
  # This method may provide some cleanup functionality in the future. You
75
81
  # better call it before you exit.
76
82
  def stop
83
+ if @pidFile
84
+ begin
85
+ File.delete(@pidFile)
86
+ rescue
87
+ warning('cannot_delete_pidfile',
88
+ "Cannote delete the PID file (#{@pidFile}): #{$!}")
89
+ end
90
+ info('daemon_deleted_pidfile', "PID file #{@pidFile} deleted")
91
+ end
92
+ end
93
+
94
+ private
95
+
96
+ def writePidFile
97
+ if @pidFile
98
+ # Prepend the current working dir to @pidFile unless it's already an
99
+ # absolute path. The working dir is changed to '/' later. We need the
100
+ # absolute name to be able to delete it on exit again.
101
+ if @pidFile[0] != '/'
102
+ @pidFile = File.join(Dir.getwd, @pidFile)
103
+ end
104
+
105
+ # If requested, write the PID of the daemon to the specified file.
106
+ begin
107
+ File.open(@pidFile, 'w') do |f|
108
+ f.puts @pid
109
+ end
110
+ rescue
111
+ warning('cannot_save_pidfile', "Cannot write PID to #{@pidFile}")
112
+ end
113
+ info('daemon_wrote_pidfile',
114
+ "PID file #{@pidFile} written with PID #{@pid}")
115
+ end
116
+
77
117
  end
78
118
 
79
119
  end
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env ruby -w
2
+ # encoding: UTF-8
3
+ #
4
+ # = DaemonConnector.rb -- The TaskJuggler III Project Management Software
5
+ #
6
+ # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012
7
+ # by Chris Schlaeger <chris@linux.com>
8
+ #
9
+ # This program is free software; you can redistribute it and/or modify
10
+ # it under the terms of version 2 of the GNU General Public License as
11
+ # published by the Free Software Foundation.
12
+ #
13
+
14
+ require 'drb'
15
+ require 'drb/acl'
16
+ require 'taskjuggler/MessageHandler'
17
+
18
+ class TaskJuggler
19
+
20
+ module DaemonConnectorMixin
21
+
22
+ include MessageHandler
23
+
24
+ def connectDaemon
25
+ unless @authKey
26
+ error('missing_auth_key', <<'EOT'
27
+ You must set an authentication key in the configuration file. Create a file
28
+ named .taskjugglerrc or taskjuggler.rc that contains at least the following
29
+ lines. Replace 'your_secret_key' with some random character sequence.
30
+
31
+ _global:
32
+ authKey: your_secret_key
33
+ EOT
34
+ )
35
+ end
36
+
37
+ uri = "druby://#{@host}:#{@port}"
38
+ if @port == 0
39
+ # If the @port is configured to 0, we need to read the URI to connect
40
+ # to the server from the .tj3d.uri file that has been generated by the
41
+ # server.
42
+ begin
43
+ uri = File.read(@uriFile).chomp
44
+ rescue
45
+ error('tjc_port_0',
46
+ 'The server port is configured to be 0, but no ' +
47
+ ".tj3d.uri file can be found: #{$!}")
48
+ end
49
+ end
50
+ debug('', "DRb URI determined as #{uri}")
51
+
52
+ # We try to play it safe here. The client also starts a DRb server, so
53
+ # we need to make sure it's constricted to localhost only. We require
54
+ # the DRb server for the standard IO redirection to work.
55
+ $SAFE = 1 unless @unsafeMode
56
+ DRb.install_acl(ACL.new(%w[ deny all
57
+ allow 127.0.0.1 ]))
58
+ DRb.start_service('druby://127.0.0.1:0')
59
+ debug('', 'DRb service started')
60
+
61
+ broker = nil
62
+ begin
63
+ # Get the ProjectBroker object from the tj3d.
64
+ broker = DRbObject.new_with_uri(uri)
65
+ # Client and server should always come from the same Gem. Since we
66
+ # restict communication to localhost, that's probably not a problem.
67
+ if (check = broker.apiVersion(@authKey, 1)) < 0
68
+ error('tjc_too_old',
69
+ 'This client is too old for the server. Please ' +
70
+ 'upgrade to a more recent version of the software.')
71
+ elsif check == 0
72
+ error('tjc_auth_fail',
73
+ 'Authentication failed. Please check your authentication ' +
74
+ 'key to match the server key.')
75
+ end
76
+ debug('', "Connection with report broker on #{uri} established")
77
+ rescue => e
78
+ # If we ended up here due to a previously reported TjRuntimeError, we
79
+ # just pass it through.
80
+ if e.is_a?(TjRuntimeError)
81
+ raise TjRuntimeError, $!
82
+ end
83
+ error('tjc_srv_not_responding',
84
+ "TaskJuggler server (tj3d) on URI '#{uri}' is not " +
85
+ "responding:\n#{$!}")
86
+ end
87
+
88
+ broker
89
+ end
90
+
91
+ def disconnectDaemon
92
+ DRb.stop_service
93
+ end
94
+
95
+ end
96
+
97
+ class DaemonConnector
98
+
99
+ include DaemonConnectorMixin
100
+
101
+ def initialize(authKey, host, port, uri)
102
+ @authKey = authKey
103
+ @host = host
104
+ @port = port
105
+ @uri = uri
106
+ @unsafeMode = true
107
+
108
+ @broker = connectDaemon
109
+ end
110
+
111
+ def disconnect
112
+ disconnectDaemon
113
+ @broker = nil
114
+ end
115
+
116
+ def getProject(projectId)
117
+ @broker.getProject(@authKey, projectId)
118
+ end
119
+
120
+ def getProjectList
121
+ @broker.getProjectList(@authKey)
122
+ end
123
+
124
+ end
125
+
126
+ end
127
+