Skip to content

Commit

Permalink
New: Web server is now a separate program: tj3webd
Browse files Browse the repository at this point in the history
  • Loading branch information
scrapper committed Feb 20, 2012
1 parent f5f265a commit fb7e2f7
Show file tree
Hide file tree
Showing 16 changed files with 419 additions and 168 deletions.
4 changes: 4 additions & 0 deletions bin/tj3webd
@@ -0,0 +1,4 @@
#!/usr/bin/env ruby

$:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
require File.basename(__FILE__)
12 changes: 10 additions & 2 deletions lib/taskjuggler/MessageHandler.rb
Expand Up @@ -115,7 +115,7 @@ class MessageHandlerInstance
include Singleton

attr_reader :messages, :errors
attr_accessor :logFile, :appName, :abortOnWarning, :baselineSFI
attr_accessor :logFile, :appName, :abortOnWarning, :trapSetup, :baselineSFI

LogLevels = { :none => 0, :fatal => 1, :error => 2,
:warning => 3, :info => 4, :debug => 5 }
Expand Down Expand Up @@ -147,6 +147,10 @@ def reset
@baselineSFI = nil
# A list of all generated messages.
@messages = []

# If this is set the true, we only throw a TjRuntimeError instead of
# using exit().
@trapSetup = false
end

# Set the console output level.
Expand Down Expand Up @@ -266,7 +270,11 @@ def addMessage(type, id, message, sourceFileInfo = nil, line = nil,
when :error
# Increase the error counter.
@errors += 1
raise TjRuntimeError
if @trapSetup
raise TjRuntimeError
else
exit 1
end
when :fatal
raise RuntimeError
end
Expand Down
8 changes: 7 additions & 1 deletion lib/taskjuggler/Tj3AppBase.rb
Expand Up @@ -117,7 +117,11 @@ def main(argv = ARGV)

# Install signal handler to exit gracefully on CTRL-C.
intHandler = Kernel.trap('INT') do
error('tj3app_user_abort', "Aborting on user request!")
begin
fatal('tj3app_user_abort', "Aborting on user request!")
rescue RuntimeError
exit 1
end
end

retVal = 0
Expand All @@ -139,7 +143,9 @@ def main(argv = ARGV)
@rc = RuntimeConfig.new(AppConfig.packageName, @configFile)

begin
MessageHandlerInstance.instance.trapSetup = true
retVal = appMain(args)
MessageHandlerInstance.instance.trapSetup = false
rescue TjRuntimeError
# We have hit a sitatuation that we can't recover from. A message
# was severed via the MessageHandler to inform the user and we now
Expand Down
73 changes: 5 additions & 68 deletions lib/taskjuggler/apps/Tj3Client.rb
Expand Up @@ -14,6 +14,7 @@
require 'drb'
require 'drb/acl'
require 'taskjuggler/Tj3AppBase'
require 'taskjuggler/daemon/DaemonConnector'

# Name of the application
AppConfig.appName = 'tj3client'
Expand All @@ -27,6 +28,8 @@ class TaskJuggler
# requires a properly configured tj3d to work.
class Tj3Client < Tj3AppBase

include DaemonConnectorMixin

def initialize
super

Expand Down Expand Up @@ -165,9 +168,10 @@ def appMain(args)
# all optional.
@rc.configure(self, 'global')

connectDaemon
@broker = connectDaemon
retVal = executeCommand(args[0], args[1..-1])
disconnectDaemon
@broker = nil

retVal
end
Expand Down Expand Up @@ -203,73 +207,6 @@ def checkCommand(args)
error('tjc_cmd_error', errorMessage)
end

def connectDaemon
unless @authKey
$stderr.puts <<'EOT'
You must set an authentication key in the configuration file. Create a file
named .taskjugglerrc or taskjuggler.rc that contains at least the following
lines. Replace 'your_secret_key' with some random character sequence.
_global:
authKey: your_secret_key
EOT
end

uri = "druby://#{@host}:#{@port}"
if @port == 0
# If the @port is configured to 0, we need to read the URI to connect
# to the server from the .tj3d.uri file that has been generated by the
# server.
begin
uri = File.read(@uriFile).chomp
rescue
error('tjc_port_0',
'The server port is configured to be 0, but no ' +
".tj3d.uri file can be found: #{$!}")
end
end

# We try to play it safe here. The client also starts a DRb server, so
# we need to make sure it's constricted to localhost only. We require
# the DRb server for the standard IO redirection to work.
$SAFE = 1 unless @unsafeMode
DRb.install_acl(ACL.new(%w[ deny all
allow 127.0.0.1 ]))
DRb.start_service('druby://127.0.0.1:0')

begin
# Get the ProjectBroker object from the tj3d.
@broker = DRbObject.new(nil, uri)
# Client and server should always come from the same Gem. Since we
# restict communication to localhost, that's probably not a problem.
if (check = @broker.apiVersion(@authKey, 1)) < 0
error('tjc_too_old',
'This client is too old for the server. Please ' +
'upgrade to a more recent version of the software.')
elsif check == 0
error('tjc_auth_fail',
'Authentication failed. Please check your authentication ' +
'key to match the server key.')
end
rescue => exception
# If we ended up here due to a previously reported TjRuntimeError, we
# just pass it through.
if exception.is_a?(TjRuntimeError)
raise TjRuntimeError, $!
end
error('tjc_srv_not_responding',
"TaskJuggler server on host '#{@host}' port " +
"#{@port} is not responding")
end

end

def disconnectDaemon
@broker = nil

DRb.stop_service
end

def executeCommand(command, args)
case command
when 'status'
Expand Down
14 changes: 0 additions & 14 deletions lib/taskjuggler/apps/Tj3Daemon.rb
Expand Up @@ -35,8 +35,6 @@ def initialize
@daemonize = true
@uriFile = File.join(Dir.getwd, '.tj3d.uri')
@port = nil
@webServer = false
@webServerPort = nil
end

def processArguments(argv)
Expand All @@ -61,16 +59,6 @@ def processArguments(argv)
'of the server.')) do |arg|
@uriFile = arg
end
@opts.on('-w', '--webserver',
format('Start a web server that serves the reports of ' +
'the loaded projects.')) do
@webServer = true
end
@opts.on('--webserver-port <NUMBER>', Integer,
format('Use the specified TCP/IP port to serve web browser ' +
'requests (Default: 8080).')) do |arg|
@webServerPort = arg
end
end
end

Expand All @@ -85,8 +73,6 @@ def appMain(files)
# command line.
broker.port = @port if @port
broker.uriFile = @uriFile.untaint
broker.enableWebServer = @webServer
broker.webServerPort = @webServerPort if @webServerPort
broker.projectFiles = sortInputFiles(files) unless files.empty?
broker.daemonize = @daemonize
# Create log files for standard IO for each child process if the daemon
Expand Down
93 changes: 93 additions & 0 deletions lib/taskjuggler/apps/Tj3WebD.rb
@@ -0,0 +1,93 @@
#!/usr/bin/env ruby -w
# encoding: UTF-8
#
# = Tj3Daemon.rb -- The TaskJuggler III Project Management Software
#
# Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012
# by Chris Schlaeger <chris@linux.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.
#

require 'drb'
require 'taskjuggler/Tj3AppBase'
require 'taskjuggler/MessageHandler'
require 'taskjuggler/daemon/WebServer'

# Name of the application
AppConfig.appName = 'tj3webd'

class TaskJuggler

class Tj3WebD < Tj3AppBase

def initialize
super
@mandatoryArgs = '[<tjp file> [<tji file> ...] ...]'

@mhi = MessageHandlerInstance.instance
@mhi.logFile = File.join(Dir.getwd, "/#{AppConfig.appName}.log")
@mhi.appName = AppConfig.appName
# By default show only warnings and more serious messages.
@mhi.outputLevel = :warning
@daemonize = true
@uriFile = File.join(Dir.getwd, '.tj3d.uri')
@port = nil
@webServerPort = nil
end

def processArguments(argv)
super do
@opts.banner += <<'EOT'
The TaskJuggler web server can be used to serve the HTTP reports of
TaskJuggler projects to be viewed by any HTML5 compliant web browser. It uses
the TaskJuggler daemon (tj3d) for data hosting and report generation.
EOT
@opts.on('-d', '--dont-daemonize',
format("Don't put program into daemon mode. Keep it " +
'connected to the terminal and show debug output.')) do
@daemonize = false
end
@opts.on('-p', '--port <NUMBER>', Integer,
format('Use the specified TCP/IP port to connect to the ' +
'TaskJuggler daemon (Default: 8474).')) do |arg|
@port = arg
end
@opts.on('--urifile', String,
format('If the port is 0, use this file to read the URI ' +
'of the TaskJuggler daemon.')) do |arg|
@uriFile = arg
end
@opts.on('--webserver-port <NUMBER>', Integer,
format('Use the specified TCP/IP port to serve web browser ' +
'requests (Default: 8080).')) do |arg|
@webServerPort = arg
end
end
end

def appMain(files)
@rc.configure(self, 'global')
@rc.configure(@mhi, 'global.log')
webServer = WebServer.new
@rc.configure(webServer, 'global')
@rc.configure(webServer, 'webd')

# Set some config variables if corresponding data was provided via the
# command line.
webServer.port = @port if @port
webServer.uriFile = @uriFile.untaint
webServer.webServerPort = @webServerPort if @webServerPort
webServer.projectFiles = sortInputFiles(files) unless files.empty?
webServer.daemonize = @daemonize

webServer.start
0
end

end

end

0 comments on commit fb7e2f7

Please sign in to comment.