halcyon 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/AUTHORS +1 -0
  2. data/LICENSE +20 -0
  3. data/README +107 -0
  4. data/Rakefile +8 -6
  5. data/bin/halcyon +3 -204
  6. data/lib/halcyon.rb +55 -42
  7. data/lib/halcyon/application.rb +247 -0
  8. data/lib/halcyon/application/router.rb +86 -0
  9. data/lib/halcyon/client.rb +187 -35
  10. data/lib/halcyon/client/ssl.rb +38 -0
  11. data/lib/halcyon/controller.rb +154 -0
  12. data/lib/halcyon/exceptions.rb +67 -59
  13. data/lib/halcyon/logging.rb +31 -0
  14. data/lib/halcyon/logging/analogger.rb +31 -0
  15. data/lib/halcyon/logging/helpers.rb +37 -0
  16. data/lib/halcyon/logging/log4r.rb +25 -0
  17. data/lib/halcyon/logging/logger.rb +20 -0
  18. data/lib/halcyon/logging/logging.rb +19 -0
  19. data/lib/halcyon/runner.rb +141 -0
  20. data/lib/halcyon/runner/commands.rb +141 -0
  21. data/lib/halcyon/runner/helpers.rb +9 -0
  22. data/lib/halcyon/runner/helpers/command_helper.rb +71 -0
  23. data/spec/halcyon/application_spec.rb +70 -0
  24. data/spec/halcyon/client_spec.rb +63 -0
  25. data/spec/halcyon/controller_spec.rb +68 -0
  26. data/spec/halcyon/halcyon_spec.rb +63 -0
  27. data/spec/halcyon/logging_spec.rb +31 -0
  28. data/spec/halcyon/router_spec.rb +37 -12
  29. data/spec/halcyon/runner_spec.rb +54 -0
  30. data/spec/spec_helper.rb +75 -9
  31. data/support/generators/halcyon/USAGE +0 -0
  32. data/support/generators/halcyon/halcyon_generator.rb +52 -0
  33. data/support/generators/halcyon/templates/README +26 -0
  34. data/support/generators/halcyon/templates/Rakefile +32 -0
  35. data/support/generators/halcyon/templates/app/application.rb +43 -0
  36. data/support/generators/halcyon/templates/config/config.yml +36 -0
  37. data/support/generators/halcyon/templates/config/init/environment.rb +11 -0
  38. data/support/generators/halcyon/templates/config/init/hooks.rb +39 -0
  39. data/support/generators/halcyon/templates/config/init/requires.rb +10 -0
  40. data/support/generators/halcyon/templates/config/init/routes.rb +50 -0
  41. data/support/generators/halcyon/templates/lib/client.rb +77 -0
  42. data/support/generators/halcyon/templates/runner.ru +8 -0
  43. data/support/generators/halcyon_flat/USAGE +0 -0
  44. data/support/generators/halcyon_flat/halcyon_flat_generator.rb +52 -0
  45. data/support/generators/halcyon_flat/templates/README +26 -0
  46. data/support/generators/halcyon_flat/templates/Rakefile +32 -0
  47. data/support/generators/halcyon_flat/templates/app.rb +49 -0
  48. data/support/generators/halcyon_flat/templates/lib/client.rb +17 -0
  49. data/support/generators/halcyon_flat/templates/runner.ru +8 -0
  50. metadata +73 -20
  51. data/lib/halcyon/client/base.rb +0 -261
  52. data/lib/halcyon/client/exceptions.rb +0 -41
  53. data/lib/halcyon/client/router.rb +0 -106
  54. data/lib/halcyon/server.rb +0 -62
  55. data/lib/halcyon/server/auth/basic.rb +0 -107
  56. data/lib/halcyon/server/base.rb +0 -774
  57. data/lib/halcyon/server/exceptions.rb +0 -41
  58. data/lib/halcyon/server/router.rb +0 -103
  59. data/spec/halcyon/error_spec.rb +0 -55
  60. data/spec/halcyon/server_spec.rb +0 -105
data/AUTHORS ADDED
@@ -0,0 +1 @@
1
+ * Matt Todd <chiology@gmail.com>
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007 Matt Todd <http://purl.org/net/maraby>.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to
5
+ deal in the Software without restriction, including without limitation the
6
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ sell copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16
+ THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+
20
+ http://www.opensource.org/licenses/mit-license.php
data/README ADDED
@@ -0,0 +1,107 @@
1
+ = Halcyon
2
+ == JSON Application Framework
3
+
4
+ A JSON Web Application Framework for developing lightweight applications
5
+ interfaced via JSON-encoded HTTP requests. This is ideal for back end
6
+ applications serving functionality for other applications.
7
+
8
+ Halcyon consists of two parts, the server application and the client. The
9
+ server application is similar to a Merb or Rails app, without the need for
10
+ implementing views, and the client is used to facilitate talking to the
11
+ application from other applications.
12
+
13
+
14
+ == On Rack
15
+
16
+ Halcyon is a Rack application, meaning that it can sit right along with any
17
+ other Rack app, such as a Merb or Rails app, and can be manipulated by any
18
+ kind of Rack middleware/filter. This means that interfacing with Halcyon in
19
+ unconventional ways is trivial since the Rack specification makes communicating
20
+ with Rack apps dead simple.
21
+
22
+
23
+ == Development
24
+
25
+ Halcyon is actively being developed by a very small community of developers and
26
+ contributors. Halcyon has seen a good deal of paradigm shift up until the 0.5.0
27
+ release, but with that release its internal API has stabilized and should
28
+ remain fairly backwards compatible from here on.
29
+
30
+ The changes made on the way to the 0.5.0 codebase were to remove all of the
31
+ server-like code to make Halcyon more application-centric and also to model
32
+ application development and structure to be more Rails- or Merb-like, though
33
+ this was just the natural evolution of Halcyon's design.
34
+
35
+
36
+ == Installation
37
+
38
+ A Gem of Halcyon is available. You can install it with:
39
+
40
+ $ sudo gem install halcyon
41
+
42
+ The latest development release can be installed with RubyGems:
43
+
44
+ $ sudo gem install halcyon --source http://halcyon.rubyforge.org/latest/
45
+
46
+ Alternatively, you can install the latest development efforts from the git
47
+ repository, located at http://github.com/mtodd/halcyon:
48
+
49
+ $ git clone git://github.com/mtodd/halcyon.git
50
+ $ cd halcyon; rake install
51
+
52
+ Don't forget to install the JSON gem for improved performance:
53
+
54
+ $ sudo gem install json
55
+
56
+ More in depth documentation can be found at
57
+ http://halcyon.rubyforge.org/docs/installation.html.
58
+
59
+
60
+ == Usage
61
+
62
+ After installing a Halcyon app, you can generate a new app, similar to the
63
+ <tt>rails</tt> or <tt>merb-gen app</tt> commands, with this:
64
+
65
+ $ halcyon init app_name
66
+
67
+ This will create a directory and generate a skeletal Halcyon application. You
68
+ can run this application without changing anything; here's how:
69
+
70
+ $ cd app_name
71
+ $ halcyon start -p 4647
72
+
73
+ A great tutorial to dive right into using Halcyon and writing apps is located
74
+ at http://halcyon.rubyforge.org/docs/tutorial.html. This will step you through
75
+ what to do, what to expect, and what it means.
76
+
77
+
78
+ == Contact
79
+
80
+ Please mail bugs, suggestions and patches to <mailto:chiology@gmail.com>.
81
+
82
+ You are also welcome to join the #halcyon channel on irc.freenode.net.
83
+
84
+ Our website is up so stop by and check out what's going down. Our address is
85
+ http://halcyon.rubyforge.org/. On there you will find information about our
86
+ mailing list as well, so do stop by.
87
+
88
+
89
+ == Thanks To
90
+
91
+ * Bill Marquette, typo correction, reviewing examples
92
+ * Elliott Cable, missing dependency, Thin testing
93
+ * ramstedt, Mongrel on JRuby port numericality issue (#14)
94
+ * Ben Simpson, PHP Client bug fixes
95
+ * Eivind Uggedal, dependencies for Router support of resources
96
+
97
+
98
+ == Links
99
+
100
+ Halcyon:: <http://halcyon.rubyforge.org/>
101
+ Aurora:: <http://aurora.rubyforge.org/>
102
+
103
+ Rack:: <http://rack.rubyforge.org/>
104
+ Merb:: <http://merbivore.com/>
105
+ JSON:: <http://json.rubyforge.org/>
106
+
107
+ Matt Todd:: <http://maraby.org/>
data/Rakefile CHANGED
@@ -4,7 +4,7 @@ $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "lib")))
4
4
 
5
5
  include FileUtils
6
6
 
7
- require 'lib/halcyon'
7
+ require 'halcyon'
8
8
 
9
9
  project = {
10
10
  :name => "halcyon",
@@ -21,13 +21,14 @@ project = {
21
21
  --op rdoc
22
22
  --line-numbers
23
23
  --inline-source
24
- --title "Halcyon\ Documentation"
24
+ --title "Halcyon\ API"
25
25
  --exclude "^(_darcs|spec|pkg|.svn)/"
26
26
  ],
27
27
  :dependencies => {
28
- 'json_pure' => '>=1.1.1',
29
- 'rack' => '>=0.2.0',
30
- 'merb' => '>=0.4.1'
28
+ 'json_pure' => '>=1.1.2',
29
+ 'rack' => '>=0.3.0',
30
+ 'merb' => '>=0.9.2',
31
+ 'rubigen' => '>=1.2.4'
31
32
  },
32
33
  :requirements => 'install the json gem to get faster JSON parsing',
33
34
  :ruby_version_required => '>=1.8.6'
@@ -37,6 +38,7 @@ BASEDIR = File.expand_path(File.dirname(__FILE__))
37
38
 
38
39
  spec = Gem::Specification.new do |s|
39
40
  s.name = project[:name]
41
+ s.rubyforge_project = project[:name]
40
42
  s.version = project[:version]
41
43
  s.platform = Gem::Platform::RUBY
42
44
  s.has_rdoc = true
@@ -55,7 +57,7 @@ spec = Gem::Specification.new do |s|
55
57
  }
56
58
  s.requirements << project[:requirements]
57
59
  s.required_ruby_version = project[:ruby_version_required]
58
- s.files = (project[:rdoc_files] + %w[Rakefile] + Dir["{spec,lib}/**/*"]).uniq
60
+ s.files = (project[:rdoc_files] + %w[Rakefile README LICENSE AUTHORS] + Dir["{spec,lib,example,support}/**/*"]).uniq
59
61
  end
60
62
 
61
63
  Rake::GemPackageTask.new(spec) do |p|
data/bin/halcyon CHANGED
@@ -1,205 +1,4 @@
1
- #!/usr/bin/env ruby -wKU
2
- #--
3
- # Created by Matt Todd on 2007-10-25.
4
- # Copyright (c) 2007. All rights reserved.
5
- #++
1
+ #!/usr/bin/env ruby
6
2
 
7
- # Blatantly stolen from Chris Neukirchen's rackup utility for running Rack
8
- # apps. (Forgive me, it just made too much sense to use your Rack bootstrap
9
- # code for my Rack bootstrap.)
10
-
11
- #--
12
- # dependencies
13
- #++
14
-
15
- %w(rubygems halcyon/server optparse).each{|dep|require dep}
16
-
17
- #--
18
- # default options
19
- #++
20
-
21
- $debug = false
22
- $test = false
23
- options = Halcyon::Server::DEFAULT_OPTIONS
24
-
25
- #--
26
- # parse options
27
- #++
28
-
29
- opts = OptionParser.new("", 24, ' ') do |opts|
30
- opts.banner << "Halcyon, JSON Server Framework\n"
31
- opts.banner << "http://halcyon.rubyforge.org/\n"
32
- opts.banner << "\n"
33
- opts.banner << "Usage: halcyon [options] appname\n"
34
- opts.banner << "\n"
35
- opts.banner << "Put -c or --config first otherwise it will overwrite higher precedence options."
36
-
37
- opts.separator ""
38
- opts.separator "Options:"
39
-
40
- opts.on("-d", "--debug", "set debugging flag (set $debug to true)") { $debug = true }
41
- opts.on("-D", "--Debug", "enable verbose debugging (set $debug and $DEBUG to true)") { $debug = true; $DEBUG = true }
42
- opts.on("-w", "--warn", "turn warnings on for your script") { $-w = true }
43
-
44
- opts.on("-I", "--include PATH", "specify $LOAD_PATH (multiples OK)") do |path|
45
- $:.unshift(*path.split(":"))
46
- end
47
-
48
- opts.on("-r", "--require LIBRARY", "require the library, before executing your script") do |library|
49
- require library
50
- end
51
-
52
- opts.on("-c", "--config PATH", "load configuration (YAML) from PATH") do |conf_file|
53
- if File.exist?(conf_file)
54
- require 'yaml'
55
-
56
- # load the config file
57
- begin
58
- conf = YAML.load_file(conf_file)
59
- rescue Errno::EACCES
60
- abort("Can't access #{conf_file}, try 'sudo #{$0}'")
61
- end
62
-
63
- # store config file path so SIGHUP and SIGUSR2 will reload the config in case it changes
64
- options[:config_file] = conf_file
65
-
66
- # parse config
67
- case conf
68
- when String
69
- # config file given was just the commandline options
70
- ARGV.replace(conf.split)
71
- opts.parse! ARGV
72
- when Hash
73
- conf.symbolize_keys!
74
- options = options.merge(conf)
75
- when Array
76
- # TODO (MT) support multiple servers (or at least specifying which
77
- # server's configuration to load)
78
- warn "Your configuration file is setup for multiple servers. This is not a supported feature yet."
79
- warn "However, we've pulled the first server entry as this server's configuration."
80
- # an array of server configurations
81
- # default to the first entry since multiple server configurations isn't
82
- # precisely worked out yet.
83
- options = options.merge(conf[0])
84
- else
85
- abort "Config file in an unsupported format. Config files must be YAML or the commandline flags"
86
- end
87
- else
88
- abort "Config file failed to load. #{conf_file} was not found. Correct the path and try again."
89
- end
90
- end
91
-
92
- opts.on("-s", "--server SERVER", "serve using SERVER (default: #{options[:server]})") do |serv|
93
- options[:server] = serv
94
- end
95
-
96
- opts.on("-o", "--host HOST", "listen on HOST (default: #{options[:host]})") do |host|
97
- options[:host] = host
98
- end
99
-
100
- opts.on("-p", "--port PORT", "use PORT (default: #{options[:port]})") do |port|
101
- options[:port] = port
102
- end
103
-
104
- opts.on("-l", "--logfile PATH", "log access to PATH (default: #{options[:log_file]})") do |log_file|
105
- options[:log_file] = log_file
106
- end
107
-
108
- opts.on("-L", "--loglevel LEVEL", "log level (default: #{options[:log_level]})") do |log_file|
109
- options[:log_level] = log_file
110
- end
111
-
112
- opts.on("-P", "--pidfile PATH", "save PID to PATH (default: #{options[:pid_file]})") do |log_file|
113
- options[:pid_file] = log_file
114
- end
115
-
116
- opts.on("-e", "--env ENVIRONMENT", "use ENVIRONMENT for defaults (default: #{options[:environment]})") do |env|
117
- options[:environment] = env
118
- end
119
-
120
- opts.on_tail("-h", "--help", "Show this message") do
121
- puts opts
122
- exit
123
- end
124
-
125
- opts.on_tail("-v", "--version", "Show version") do
126
- # require 'halcyon'
127
- puts "Halcyon #{Halcyon::Server.version}"
128
- exit
129
- end
130
-
131
- begin
132
- opts.parse! ARGV
133
- rescue OptionParser::InvalidOption => e
134
- abort "You used an unsupported option. Try: halcyon -h"
135
- end
136
- end
137
-
138
- abort "Halcyon needs an app to run. Try: halcyon -h" if ARGV.empty?
139
- options[:app] = ARGV.shift
140
-
141
- #--
142
- # load app
143
- #++
144
-
145
- if !File.exists?("#{options[:app]}.rb")
146
- abort "Halcyon did not find the app #{options[:app]}. Check your path and try again."
147
- end
148
-
149
- require options[:app]
150
- appname = File.basename(options[:app]).capitalize.gsub(/_([a-z])/){|m|m[1].chr.capitalize}
151
- begin
152
- app = Object.const_get(appname)
153
- rescue NameError => e
154
- abort "Unable to load #{appname}. Please ensure your server is so named."
155
- end
156
-
157
- #--
158
- # prepare server
159
- #++
160
- begin
161
- # attempt to require the server
162
- begin; require options[:server].capitalize; rescue LoadError; end
163
-
164
- # get the appropriate Rack Handler
165
- server = Rack::Handler.const_get(options[:server].capitalize)
166
- rescue NameError
167
- servers = {
168
- 'cgi' => 'CGI',
169
- 'fastcgi' => 'FastCGI',
170
- 'lsws' => 'LSWS',
171
- 'mongrel' => 'Mongrel',
172
- 'webrick' => 'WEBrick',
173
- 'thin' => 'Thin'
174
- }
175
- abort "Unsupported server (missing Rack Handler). Did you mean to specify #{options[:server]}?" unless servers.key? options[:server]
176
- server = Rack::Handler.const_get(servers[options[:server]])
177
- end
178
-
179
- #--
180
- # prepare app environment
181
- #++
182
-
183
- case options[:environment]
184
- when "development"
185
- app = Rack::Builder.new {
186
- use Rack::CommonLogger, STDERR unless server.name =~ /CGI/
187
- use Rack::ShowExceptions
188
- use Rack::Reloader
189
- use Rack::Lint
190
- run app.new(options)
191
- }.to_app
192
- when "deployment"
193
- app = Rack::Builder.new {
194
- use Rack::CommonLogger, STDERR unless server.name =~ /CGI/
195
- run app.new(options)
196
- }.to_app
197
- else
198
- app = app.new(options)
199
- end
200
-
201
- #--
202
- # start server
203
- #++
204
-
205
- server.run app, :Port => Integer(options[:port])
3
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'halcyon')
4
+ Halcyon::Runner.run! ARGV
data/lib/halcyon.rb CHANGED
@@ -1,54 +1,67 @@
1
- #!/usr/bin/env ruby
2
- #--
3
- # Created by Matt Todd on 2007-12-14.
4
- # Copyright (c) 2007. All rights reserved.
5
- #++
6
-
7
1
  $:.unshift File.dirname(__FILE__)
8
2
 
9
- #--
10
- # dependencies
11
- #++
12
-
13
- %w(rubygems merb/core_ext).each {|dep|require dep}
14
-
15
- #--
16
- # module
17
- #++
3
+ %w(rubygems rack merb-core/core_ext merb-core/vendor/facets merb-core/dispatch/router json uri).each {|dep|require dep}
18
4
 
5
+ # Provides global values, like the root of the current application directory,
6
+ # the current logger, the application name, and the framework version.
7
+ #
8
+ # Examples
9
+ # Halcyon.app #=> AppName
10
+ # Halcyon.root #=> Dir.pwd
11
+ # Halcyon.config #=> {:allow_from => :all, :logging => {...}, ...}
12
+ # Halcyon.paths #=> {:config => Halcyon.root/'config', ...}
13
+ # Halcyon.logger #=> #<Logger>
14
+ # Halcyon.version #=> "0.5.0"
19
15
  module Halcyon
20
- VERSION = [0,4,0]
21
- def self.version
22
- VERSION.join('.')
23
- end
24
16
 
25
- # = Introduction
26
- #
27
- # Halcyon is a JSON Web Server Framework intended to be used for fast, small
28
- # data transactions, like for AJAX-intensive sites or for special services like
29
- # authentication centralized for numerous web apps in the same cluster.
30
- #
31
- # The possibilities are pretty limitless: the goal of Halcyon was simply to be
32
- # lightweight, fast, simple to implement and use, and able to be extended.
33
- #
34
- # == Usage
35
- #
36
- # For documentation on using Halcyon, check out the Halcyon::Server::Base and
37
- # Halcyon::Client::Base classes which contain much more usage documentation.
38
- def introduction
39
- abort "READ THE DAMNED RDOCS!"
40
- end
17
+ VERSION = [0,5,0] unless defined?(Halcyon::VERSION)
41
18
 
42
- #--
43
- # Module Autoloading
44
- #++
19
+ autoload :Application, 'halcyon/application'
20
+ autoload :Client, 'halcyon/client'
21
+ autoload :Controller, 'halcyon/controller'
22
+ autoload :Exceptions, 'halcyon/exceptions'
23
+ autoload :Logging, 'halcyon/logging'
24
+ autoload :Runner, 'halcyon/runner'
45
25
 
46
- class Server
47
- module Auth
48
- autoload :Basic, 'halcyon/server/auth/basic'
26
+ class << self
27
+
28
+ attr_accessor :app
29
+ attr_accessor :logger
30
+ attr_accessor :config
31
+ attr_accessor :paths
32
+
33
+ def version
34
+ VERSION.join('.')
35
+ end
36
+
37
+ # The root directory of the current application.
38
+ #
39
+ # Returns String:root_directory
40
+ def root
41
+ self.config[:root] || Dir.pwd rescue Dir.pwd
49
42
  end
43
+
44
+ def configurable(attribute)
45
+ eval <<-"end;"
46
+ def #{attribute.to_s}
47
+ Halcyon.config[:#{attribute.to_s}]
48
+ end
49
+ def #{attribute.to_s}=(value)
50
+ value = value.to_mash if value.is_a?(Hash)
51
+ Halcyon.config[:#{attribute.to_s}] = value
52
+ end
53
+ end;
54
+ end
55
+ alias_method :configurable_attr, :configurable
56
+
50
57
  end
51
58
 
59
+ # Creates <tt>Halcyon.db</tt> to alias <tt>Halcyon.config[:db]</tt>.
60
+ # Also creates the complementary assignment method, <tt>Halcyon.db=</tt>
61
+ # that aliases <tt>Halcyon.config[:db]=</tt>.
62
+ configurable_attr :db
63
+
52
64
  end
53
65
 
54
- %w(halcyon/exceptions).each {|dep|require dep}
66
+ # Include the klass#logger and klass.logger accessor methods into Object.
67
+ Object.send(:include, Halcyon::Logging::Helpers)