# $Id: server.rb,v 1.23 2004/04/23 17:05:47 eto Exp $
# Copyright (C) 2003-2004 Kouichirou Eto, All rights reserved.
# This is free software with ABSOLUTELY NO WARRANTY.
# You can redistribute it and/or modify it under the terms of the GNU GPL2.

require 'webrick'
require 'qwik/webrick'
require 'qwik/config'
require 'qwik/util'
require 'qwik/session'
require 'qwik/qxml'
require 'qwik/generator'

module Qwik
  class Server < WEBrick::HTTPServer
    def initialize(qwikconfig)
      @qwikconfig  = qwikconfig
      @logfile  = @qwikconfig.log_file.dup
      @alogfile = @qwikconfig.accesslog_file.dup
      @pidfile  = @qwikconfig.pid_file.dup

      @qwikmemory = ServerMemory.new(@qwikconfig)

      loglevel = WEBrick::Log::INFO
      servertype = WEBrick::Daemon
      format = WEBrick::AccessLog::COMBINED_LOG_FORMAT

      @port = @qwikconfig.port
      if @qwikconfig.ssl
	require 'webrick/https'
	@logfile += '-ssl'
	@alogfile += '-ssl'
	@pidfile += '-ssl'
	@port = 443 if @port == 80
      end

      if @qwikconfig.debug
	require 'qwik/autoreload'
	autoreload(1, true) # auto reload
	Thread.abort_on_exception = true
	@pidfile += '-d'
	servertype = WEBrick::SimpleServer
	if ! @qwikconfig.test
	  @logfile = $stderr
	  @alogfile = $stderr
	end
	format = "%l %u \"%r\" %s %b"
      end
      basic_log = WEBrick::BasicLog::new(@alogfile, loglevel)

      webrick_config = {
	:BindAddress    => @qwikconfig.bind_address,
	:Port           => @port,
	:Logger         => WEBrick::Log::new(@logfile, loglevel),
	:ServerType     => servertype,
	:StartCallback  => Proc.new { start_server() },
	:AccessLog      => [[ basic_log, format ]],
	:ServerSoftware => 'qwikWeb/0.1',
	:QwikConfig     => @qwikconfig,
	:QwikMemory     => @qwikmemory,
      }

      if @qwikconfig.ssl
	sslconfig = {
	  :SSLEnable       => true,
	  :SSLVerifyClient => ::OpenSSL::SSL::VERIFY_NONE,
	  :SSLCertName => [ ["C","JP"], ["O","qwik.jp"], ["CN", "WWW"] ]
	}
	webrick_config.update(sslconfig)
      end

      super(webrick_config)

      mount("/", Servlet)
    end

    def start_server
      write_pid_file
    end

    def write_pid_file
      File.open(@pidfile, "wb") {|f| f.puts Process.pid }
    end

    def read_pid_file
      open(@pidfile, 'rb'){|f| f.read}.chomp.to_i
    end

    def remove_pid_file
      File.unlink(@pidfile) if Process.pid == read_pid_file
    end
  end

  class ServerMemory
    def initialize(config)
      @config = config
    end

    def farm
      @farm = Farm.new(@config) if @farm.nil?
      @farm
    end
  end
end
