public
Rubygem
Description: JSON Web App Framework
Homepage: http://halcyon.rubyforge.org/
Clone URL: git://github.com/mtodd/halcyon.git
Click here to lend your support to: halcyon and make a donation at www.pledgie.com !
halcyon / lib / halcyon / runner.rb
100644 142 lines (121 sloc) 4.805 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
module Halcyon
  
  # Handles initializing and running the application, including:
  # * setting up the logger
  # * loading initializers
  # * loading controllers
  #
  # The Runner is a full-fledged Rack application, and accepts calls to #call.
  #
  # Also handles running commands form the command line.
  #
  # Examples
  # # start serving the current app (in .)
  # Halcyon::Runner.run!(['start', '-p', '4647'])
  #
  # # load the config file and initialize the app
  # Halcyon::Runner.load_config Halcyon.root/'config'/'config.yml'
  # Halcyon::Runner.new
  class Runner
    
    autoload :Commands, 'halcyon/runner/commands'
    
    class << self
      
      # Runs commands from the CLI.
      # +argv+ the arguments to pass to the commands
      #
      # Returns nothing
      def run!(argv=ARGV)
        Commands.send(argv.shift, argv)
      end
      
      # Returns the path to the configuration file specified, defaulting
      # to the path for the <tt>config.yml</tt> file.
      # +file+ the name of the config file path (without the <tt>.yml</tt>
      # extension)
      def config_path(file = "config")
        Halcyon.paths[:config]/"#{file}.yml"
      end
      
    end
    
    # Initializes the application and application resources.
    def initialize
      Halcyon::Runner.load_paths if Halcyon.paths.nil?
      
      # Load the configuration if none is set already
      if Halcyon.config.nil?
        if File.exist?(Halcyon::Runner.config_path)
          Halcyon.config = Halcyon::Runner.load_config
        else
          Halcon.config = Halcyon::Application::DEFAULT_OPTIONS
        end
      end
      
      # Set application name
      Halcyon.app = Halcyon.config[:app] || Halcyon.root.split('/').last.camel_case
      
      # Setup logger
      if Halcyon.config[:logger]
        Halcyon.config[:logging] = (Halcyon.config[:logging] || Halcyon::Application::DEFAULT_OPTIONS[:logging]).merge({
          :type => Halcyon.config[:logger].class.to_s,
          :logger => Halcyon.config[:logger]
        })
      end
      Halcyon::Logging.set((Halcyon.config[:logging][:type] rescue nil))
      Halcyon.logger = Halcyon::Logger.setup(Halcyon.config[:logging])
      
      # Run initializers
      Dir.glob(Halcyon.paths[:init]/'{requires,hooks,routes,environment,*}.rb').each do |initializer|
        self.logger.debug "Init: #{File.basename(initializer).chomp('.rb').camel_case}" if
        require initializer.chomp('.rb')
      end
      
      # Setup autoloads for Controllers found in Halcyon.root/'app'
      Dir.glob(Halcyon.paths[:controller]/'{application,*}.rb').each do |controller|
        self.logger.debug "Load: #{File.basename(controller).chomp('.rb').camel_case} Controller" if
        require controller.chomp('.rb')
      end
      
      @app = Halcyon::Application.new
    end
    
    # Calls the application, which gets proxied to the dispatcher.
    # +env+ the request environment details
    #
    # Returns [Fixnum:status, {String:header => String:value}, [String:body]]
    def call(env)
      @app.call(env)
    end
    
    class << self
      
      # Loads the configuration file specified into <tt>Halcyon.config</tt>.
      # +file+ the configuration file to load
      #
      # Examples
      # Halcyon::Runner.load_config Halcyon.root/'config'/'config.yml'
      # Halcyon.config #=> {:allow_from => :all, :logging => {...}, ...}.to_mash
      #
      # Returns {Symbol:key => String:value}.to_mash
      def load_config(file=Halcyon::Runner.config_path)
        if File.exist?(file)
          require 'yaml'
          
          # load the config file
          begin
            config = YAML.load_file(file).to_mash
          rescue Errno::EACCES
            raise LoadError.new("Can't access #{file}, try 'sudo #{$0}'")
          end
        else
          warn "#{file} not found, ensure the path to this file is correct. Ignoring."
          nil
        end
      end
      
      # Set the paths for resources to be located.
      #
      # Used internally for setting the load paths if not manually overridden
      # and needed to be set before normal application initialization.
      #
      # TODO: Move this to the planned <tt>Halcyon::Config</tt> object.
      #
      # Returns nothing.
      def load_paths
        # Set the default application paths, not overwriting manually set paths
        Halcyon.paths = {
          :controller => Halcyon.root/'app',
          :model => Halcyon.root/'app'/'models',
          :lib => Halcyon.root/'lib',
          :config => Halcyon.root/'config',
          :init => Halcyon.root/'config'/'{init,initialize}',
          :log => Halcyon.root/'log'
        }.to_mash.merge(Halcyon.paths || {})
      end
      
    end
    
  end
end