rave 0.1.1 → 0.1.2

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.
data/bin/rave CHANGED
@@ -1,24 +1,28 @@
1
- #!/usr/bin/env ruby
2
-
3
- here = File.dirname(__FILE__)
4
- %w( create server usage war ).each do |cmd|
5
- require File.join(here, "..", "lib", "commands", cmd)
6
- end
7
-
8
- args = ARGV
9
- cmd = args.shift
10
-
11
- if cmd
12
- case cmd
13
- when "create"
14
- create_robot(args)
15
- when "server"
16
- start_robot(args)
17
- when "war"
18
- create_war(args)
19
- else
20
- display_usage
21
- end
22
- else
23
- usage
1
+ #!/usr/bin/env ruby
2
+
3
+ here = File.dirname(__FILE__)
4
+ %w( create server usage war appcfg ).each do |cmd|
5
+ require File.join(here, "..", "lib", "commands", cmd)
6
+ end
7
+
8
+ args = ARGV
9
+ cmd = args.shift
10
+
11
+ if cmd
12
+ case cmd
13
+ when "create"
14
+ create_robot(args)
15
+ when "server"
16
+ start_robot(args)
17
+ when "war"
18
+ create_war(args)
19
+ when "cleanup"
20
+ cleanup_war(args)
21
+ when "appengine_deploy"
22
+ appcfg_update(args)
23
+ else
24
+ display_usage
25
+ end
26
+ else
27
+ display_usage
24
28
  end
@@ -0,0 +1,9 @@
1
+ #Does an appcfg update to deploy the tmp/war folder to appengine
2
+ def appcfg_update(args)
3
+ Rake.application.standard_exception_handling do
4
+ Rake.application.init
5
+ Rave::Task.new
6
+ task(:default => "rave:appcfg_update")
7
+ Rake.application.top_level
8
+ end
9
+ end
@@ -1,147 +1,153 @@
1
- require 'ftools'
2
-
3
- #Creates a project for a robot. Args are:
4
- # => robot_name (required)
5
- # => image_url=http://imageurl.com/ (optional)
6
- # => profile_url=http://profileurl.com/ (optional)
7
- # e.g. rave my_robot image_url=http://appropriate-casey.appspot.com/image.png profile_url=http://appropriate-casey.appspot.com/profile.json
8
- def create_robot(args)
9
- robot_name = args.first
10
- module_name = robot_name.split(/_|-/).collect { |word| word[0, 1].upcase + word[1, word.length-1] }.join("")
11
- robot_class_name = "#{module_name}::Robot"
12
- options = { :name => robot_name }
13
- args[1, args.length-1].each do |arg|
14
- key, value = arg.split("=").collect { |part| part.strip }
15
- options[key.to_sym] = value
16
- end
17
- dir = File.join(".", robot_name)
18
- lib = File.join(dir, "lib")
19
- config_dir = File.join(dir, "config")
20
- file = File.join(dir, "robot.rb")
21
- appengine_web = File.join(dir, "appengine-web.xml")
22
- config = File.join(dir, "config.ru")
23
- here = File.dirname(__FILE__)
24
- jar_dir = File.join(here, "..", "jars")
25
- jars = %w( appengine-api-1.0-sdk-1.2.1.jar jruby-core.jar ruby-stdlib.jar )
26
- #Create the project dir
27
- puts "Creating directory #{File.expand_path(dir)}"
28
- Dir.mkdir(dir)
29
- puts "Creating robot class #{File.expand_path(file)}"
30
- #Make the base robot class
31
- File.open(file, "w") do |f|
32
- f.puts robot_file_contents(module_name)
33
- end
34
- #Make the rackup config file
35
- puts "Creating rackup config file #{File.expand_path(config)}"
36
- options_str = options.collect { |key, val| ":#{key} => \"#{val}\"" }.join(", ")
37
- File.open(config, "w") do |f|
38
- f.puts config_file_contents(robot_class_name, options_str)
39
- end
40
- #Make the appengine web xml file
41
- puts "Creating appengine config file #{File.expand_path(appengine_web)}"
42
- File.open(appengine_web, "w") do |f|
43
- f.puts appengine_web_contents(robot_name)
44
- end
45
- #Copy jars over
46
- puts "Creating lib directory #{File.expand_path(lib)}"
47
- Dir.mkdir(lib)
48
- jars.each do |jar|
49
- puts "Adding jar #{jar}"
50
- File.copy(File.join(jar_dir, jar), File.join(lib, jar))
51
- end
52
- #Make the wabler config file
53
- puts "Creating config directory #{File.expand_path(config_dir)}"
54
- Dir.mkdir(config_dir)
55
- warble_file = File.join(config_dir, "warble.rb")
56
- puts "Creating warble config file #{File.expand_path(warble_file)}"
57
- File.open(warble_file, "w") do |f|
58
- f.puts warble_config_contents()
59
- end
60
- end
61
-
62
- def robot_file_contents(module_name)
63
- <<-ROBOT
64
- require 'rubygems'
65
- require 'rave'
66
-
67
- module #{module_name}
68
- class Robot < Rave::Models::Robot
69
-
70
- ME = "appropriate-casey@appspot.com"
71
-
72
- #Define handlers here:
73
- # e.g. if the robot should act on a DOCUMENT_CHANGED event:
74
- #
75
- # def document_changed(event, context)
76
- # #Do some stuff
77
- # end
78
- #
79
- # Events are:
80
- #
81
- # WAVELET_BLIP_CREATED, WAVELET_BLIP_REMOVED, WAVELET_PARTICIPANTS_CHANGED,
82
- # WAVELET_TIMESTAMP_CHANGED, WAVELET_TITLE_CHANGED, WAVELET_VERSION_CHANGED,
83
- # BLIP_CONTRIBUTORS_CHANGED, BLIP_DELETED, BLIP_SUBMITTED, BLIP_TIMESTAMP_CHANGED,
84
- # BLIP_VERSION_CHANGED, DOCUMENT_CHANGED, FORM_BUTTON_CLICKED
85
- #
86
- # If you want to name your event handler something other than the default name,
87
- # or you need to have more than one handler for an event, you can register handlers
88
- # in the robot's constructor:
89
- #
90
- # def initialize(options={})
91
- # super
92
- # register_handler(Rave::Models::Event::DOCUMENT_CHANGED, :custom_doc_changed_handler)
93
- # end
94
- #
95
- # def custom_doc_changed_handler(event, context)
96
- # #Do some stuff
97
- # end
98
- #
99
- # Note: Don't forget to call super if you define #initialize
100
-
101
- end
102
- end
103
- ROBOT
104
- end
105
-
106
- def config_file_contents(robot_class_name, options_str)
107
- <<-CONFIG
108
- require 'robot'
109
- run #{robot_class_name}.new( #{options_str} )
110
- CONFIG
111
- end
112
-
113
- def appengine_web_contents(robot_name)
114
- <<-APPENGINE
115
- <?xml version="1.0" encoding="utf-8"?>
116
- <appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
117
- <application>#{robot_name}</application>
118
- <version>1</version>
119
- <static-files />
120
- <resource-files />
121
- <sessions-enabled>false</sessions-enabled>
122
- <system-properties>
123
- <property name="jruby.management.enabled" value="false" />
124
- <property name="os.arch" value="" />
125
- <property name="jruby.compile.mode" value="JIT"/> <!-- JIT|FORCE|OFF -->
126
- <property name="jruby.compile.fastest" value="true"/>
127
- <property name="jruby.compile.frameless" value="true"/>
128
- <property name="jruby.compile.positionless" value="true"/>
129
- <property name="jruby.compile.threadless" value="false"/>
130
- <property name="jruby.compile.fastops" value="false"/>
131
- <property name="jruby.compile.fastcase" value="false"/>
132
- <property name="jruby.compile.chainsize" value="500"/>
133
- <property name="jruby.compile.lazyHandles" value="false"/>
134
- <property name="jruby.compile.peephole" value="true"/>
135
- </system-properties>
136
- </appengine-web-app>
137
- APPENGINE
138
- end
139
-
140
- def warble_config_contents
141
- <<-WARBLE
142
- Warbler::Config.new do |config|
143
- config.gems = %w( rave json-jruby rack builder )
144
- config.includes = %w( robot.rb appengine-web.xml )
145
- end
146
- WARBLE
147
- end
1
+ require 'ftools'
2
+
3
+ #Creates a project for a robot. Args are:
4
+ # => robot_name (required)
5
+ # => image_url=http://imageurl.com/icon.png (optional)
6
+ # => profile_url=http://profileurl.com/ (optional)
7
+ # e.g. rave my_robot image_url=http://appropriate-casey.appspot.com/image.png profile_url=http://appropriate-casey.appspot.com/profile.json
8
+ def create_robot(args)
9
+ robot_name = args.first
10
+ module_name = robot_name.split(/_|-/).collect { |word| word.capitalize }.join
11
+ robot_class_name = "#{module_name}::Robot"
12
+
13
+ options = { :name => robot_name, :version => 1, :id => "#{robot_name}@appspot.com" }
14
+ args[1, args.length-1].each do |arg|
15
+ key, value = arg.split("=").collect { |part| part.strip }
16
+ options[key.to_sym] = value
17
+ end
18
+
19
+ dir = File.join(".", robot_name)
20
+ if File.exist? dir
21
+ puts "Directory #{dir}/ already exists. Exiting..."
22
+ exit
23
+ end
24
+
25
+ lib = File.join(dir, "lib")
26
+ config_dir = File.join(dir, "config")
27
+ file = File.join(dir, "robot.rb")
28
+ run = File.join(dir, "config.ru")
29
+ config = File.join(dir, "config.yaml")
30
+ public_folder = File.join(dir, "public")
31
+ html = File.join(public_folder, "index.html")
32
+
33
+ #Create the project dir
34
+ puts "Creating directory #{File.expand_path(dir)}"
35
+ Dir.mkdir(dir)
36
+
37
+ puts "Creating robot class #{File.expand_path(file)}"
38
+ #Make the base robot class
39
+ File.open(file, "w") do |f|
40
+ f.puts robot_file_contents(module_name)
41
+ end
42
+
43
+ # Make the rackup run file.
44
+ puts "Creating rackup config file #{File.expand_path(run)}"
45
+ File.open(run, "w") do |f|
46
+ f.puts run_file_contents(robot_class_name, file)
47
+ end
48
+
49
+ # Make up the yaml config file.
50
+ puts "Creating configuration file #{File.expand_path(config)}"
51
+ File.open(config, "w") do |f|
52
+ f.puts config_file_contents(options)
53
+ end
54
+
55
+ #Make the public folder for static resources
56
+ puts "Creating public folder"
57
+ Dir.mkdir(public_folder)
58
+
59
+ # Make up the html index file.
60
+ puts "Creating html index file #{File.expand_path(html)}"
61
+ File.open(html, "w") do |f|
62
+ f.puts html_file_contents(robot_name, options[:id], options[:image_url])
63
+ end
64
+
65
+ #Create lib directory
66
+ puts "Creating lib directory #{File.expand_path(lib)}"
67
+ Dir.mkdir(lib)
68
+ end
69
+
70
+ def robot_file_contents(module_name)
71
+ <<-ROBOT
72
+ require 'rubygems'
73
+ require 'rave'
74
+
75
+ module #{module_name}
76
+ class Robot < Rave::Models::Robot
77
+ #Define handlers here:
78
+ # e.g. if the robot should act on a DOCUMENT_CHANGED event:
79
+ #
80
+ # def document_changed(event, context)
81
+ # #Do some stuff
82
+ # end
83
+ #
84
+ # Events are:
85
+ #
86
+ # WAVELET_BLIP_CREATED, WAVELET_BLIP_REMOVED, WAVELET_PARTICIPANTS_CHANGED,
87
+ # WAVELET_TIMESTAMP_CHANGED, WAVELET_TITLE_CHANGED, WAVELET_VERSION_CHANGED,
88
+ # BLIP_CONTRIBUTORS_CHANGED, BLIP_DELETED, BLIP_SUBMITTED, BLIP_TIMESTAMP_CHANGED,
89
+ # BLIP_VERSION_CHANGED, DOCUMENT_CHANGED, FORM_BUTTON_CLICKED
90
+ #
91
+ # If you want to name your event handler something other than the default name,
92
+ # or you need to have more than one handler for an event, you can register handlers
93
+ # in the robot's constructor:
94
+ #
95
+ # def initialize(options={})
96
+ # super
97
+ # register_handler(Rave::Models::Event::DOCUMENT_CHANGED, :custom_doc_changed_handler)
98
+ # end
99
+ #
100
+ # def custom_doc_changed_handler(event, context)
101
+ # #Do some stuff
102
+ # end
103
+ #
104
+ # Note: Don't forget to call super if you define #initialize
105
+
106
+ end
107
+ end
108
+ ROBOT
109
+ end
110
+
111
+ def run_file_contents(robot_class_name, robot_file)
112
+ <<-CONFIG
113
+ require '#{File.basename(robot_file).chomp(File.extname(robot_file))}'
114
+ run #{robot_class_name}.instance
115
+ CONFIG
116
+ end
117
+
118
+ def config_file_contents(options)
119
+ <<-CONFIG
120
+ robot:
121
+ id: #{options[:id]}
122
+ name: #{options[:name]}
123
+ image_url: #{options[:image_url]}
124
+ profile_url: #{options[:profile_url]}
125
+ version: #{options[:version]}
126
+ appcfg:
127
+ version: 1
128
+ # Uncomment this section to add gems required by your robot.
129
+ # They will unpacked in your project at appengine deploy time
130
+ # gems:
131
+ # - some_gem # Replace this with the name of the gem you require
132
+ # - some_other_gem # Replace this with the name of the gem you require
133
+ CONFIG
134
+ end
135
+
136
+ def html_file_contents(name, id, image_url)
137
+ img_tag = image_url ? "\n <img src=\"#{image_url}\" alt=\"#{name} icon\" />\n" : ""
138
+ <<-HTML
139
+ <html>
140
+ <head>
141
+ <title>#{name}</title>
142
+ </head>
143
+ <body>
144
+ <h1>#{name}</h1>
145
+ #{img_tag}
146
+ <p>This is a Google Wave robot using <a href="http://github.com/diminish7/rave">Rave</a> running in JRuby.
147
+ Use this robot in your Google Waves by adding <em>#{id}</em> as a participant</p>
148
+
149
+ <img src="http://code.google.com/appengine/images/appengine-silver-120x30.gif" alt="Powered by Google App Engine" />
150
+ </body>
151
+ </html>
152
+ HTML
153
+ end
@@ -1,8 +1,8 @@
1
- #Starts up rack based on the config.ru file in the working directory
2
- # Note that this is of limited use right now, because robots have to
3
- # run on appengine. Better to test locally with the appengine sdk
4
- def start_robot(args)
5
- cmd = (RUBY_PLATFORM == 'java') ? "jruby -S rackup" : "rackup"
6
- cmd += " " + args.join(" ") if args
7
- exec(cmd)
1
+ #Starts up rack based on the config.ru file in the working directory
2
+ # Note that this is of limited use right now, because robots have to
3
+ # run on appengine. Better to test locally with the appengine sdk
4
+ def start_robot(args)
5
+ cmd = (RUBY_PLATFORM == 'java') ? "jruby -S rackup" : "rackup"
6
+ cmd += " " + args.join(" ") if args
7
+ exec(cmd)
8
8
  end
@@ -0,0 +1,156 @@
1
+ require 'rake'
2
+ require 'rake/tasklib'
3
+ require 'fileutils'
4
+ require 'yaml'
5
+ require 'warbler'
6
+
7
+ module Rave
8
+ class Task < Warbler::Task
9
+
10
+ REQUIRED_GEMS = ["rave", "json-jruby", "rack", "builder", "RedCloth"]
11
+
12
+ def initialize
13
+ warbler_config = Warbler::Config.new do |config|
14
+ config.gems = ((robot_config['gems'] || []) + REQUIRED_GEMS).uniq
15
+ config.includes = %w( robot.rb config.yaml )
16
+ end
17
+ super(:rave, warbler_config)
18
+ define_post_war_processes
19
+ define_deploy_task
20
+ end
21
+
22
+ private
23
+
24
+ def robot_config
25
+ @robot_config ||= YAML::load(File.open(File.join(".", "config.yaml")))
26
+ end
27
+
28
+ def define_post_war_processes
29
+ namespace :rave do
30
+ desc "Post-War cleanup"
31
+ task :create_war => 'rave' do
32
+ #TODO: This needs to only run through this if the files have changed
33
+ #Get config info
34
+ web_inf = File.join(".", "tmp", "war", "WEB-INF")
35
+ rave_jars = File.join(File.dirname(__FILE__), "..", "jars")
36
+ #Cleanup unneeded gems that warbler copies in
37
+ cleanup_gems(File.join(web_inf, "gems", "gems"), robot_config['gems'] || [])
38
+ #Copy the appengine sdk jar to the robot
39
+ copy_appengine_jar_to_robot(rave_jars, File.join(web_inf, "lib"))
40
+ #Fix the broken paths in json-jruby
41
+ fix_json_jruby_paths(File.join(web_inf, "gems", "gems"))
42
+ #Add the appengine-web.xml file
43
+ robot_name = robot_config['robot']['id'].gsub(/@.+/, '')
44
+ version = robot_config['appcfg'] && robot_config['appcfg']['version'] ? robot_config['appcfg']['version'] : 1
45
+ create_appengine_web(File.join(web_inf, "appengine-web.xml"), robot_name, version)
46
+ end
47
+ end
48
+ end
49
+
50
+ def define_deploy_task
51
+ namespace :rave do
52
+ desc "Deploy to Appengine"
53
+ task :appcfg_update => :create_war do
54
+ staging_folder = File.join(".", "tmp", "war")
55
+ sdk_path = find_sdk
56
+ if sdk_path
57
+ appcfg_jar = File.expand_path(File.join(sdk_path, 'lib', 'appengine-tools-api.jar'))
58
+ require appcfg_jar
59
+ Java::ComGoogleAppengineToolsAdmin::AppCfg.main(["update", staging_folder].to_java(:string))
60
+ else
61
+ puts "Unable to find the Google Appengine Java SDK"
62
+ puts "You can either"
63
+ puts "1. Define the path to the main SDK folder in config.yaml - e.g.:"
64
+ puts "appcfg:"
65
+ puts " sdk: /usr/local/appengine-java-sdk/"
66
+ puts "2. Add the SDK bin folder to your PATH, or"
67
+ puts "3. Create an environment variable APPENGINE_JAVA_SDK that defines the path to the main SDK folder"
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ #Remove warbler and jruby-jars - added by warbler but unneeded
74
+ def cleanup_gems(gem_dir, gems)
75
+ ["warbler", "jruby-jars"].each do |g|
76
+ dir = Dir[File.join(gem_dir, "#{g}*")].first
77
+ unless dir.nil? || gems.include?(g)
78
+ puts "Removing #{g} from war"
79
+ FileUtils.rm_rf(dir)
80
+ end
81
+ end
82
+ end
83
+
84
+ def copy_appengine_jar_to_robot(rave_jar_dir, warbler_jar_dir)
85
+ jar = "appengine-api-1.0-sdk-1.3.0.jar"
86
+ rave_jar = File.join(rave_jar_dir, jar)
87
+ warbler_jar = File.join(warbler_jar_dir, jar)
88
+ puts "Copying appengine jar from #{rave_jar} to #{warbler_jar}"
89
+ File.copy(rave_jar, warbler_jar)
90
+ end
91
+
92
+ def fix_json_jruby_paths(web_inf_gems)
93
+ #TODO: Why is this necessary? Is this an appengine issue?
94
+ puts "Fixing paths in json-jruby"
95
+ ext = Dir[File.join(web_inf_gems, "json-jruby-*", "lib", "json", "ext.rb")].first
96
+ if ext
97
+ text = File.open(ext, "r") { |f| f.read }
98
+ text.gsub!("require 'json/ext/parser'", "require 'ext/parser'")
99
+ text.gsub!("require 'json/ext/generator'", "require 'ext/generator'")
100
+ File.open(ext, "w") { |f| f.write(text) }
101
+ end
102
+ end
103
+
104
+ def create_appengine_web(path, robot_name, version)
105
+ puts "Creating appengine config file #{File.expand_path(path)}"
106
+ File.open(path, "w") do |f|
107
+ f.puts appengine_web_contents(robot_name, version)
108
+ end
109
+ end
110
+
111
+ def appengine_web_contents(robot_name, version)
112
+ <<-APPENGINE
113
+ <?xml version="1.0" encoding="utf-8"?>
114
+ <appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
115
+ <application>#{robot_name}</application>
116
+ <version>#{version}</version>
117
+ <static-files />
118
+ <resource-files />
119
+ <sessions-enabled>false</sessions-enabled>
120
+ <system-properties>
121
+ <property name="jruby.management.enabled" value="false" />
122
+ <property name="os.arch" value="" />
123
+ <property name="jruby.compile.mode" value="JIT"/> <!-- JIT|FORCE|OFF -->
124
+ <property name="jruby.compile.fastest" value="true"/>
125
+ <property name="jruby.compile.frameless" value="true"/>
126
+ <property name="jruby.compile.positionless" value="true"/>
127
+ <property name="jruby.compile.threadless" value="false"/>
128
+ <property name="jruby.compile.fastops" value="false"/>
129
+ <property name="jruby.compile.fastcase" value="false"/>
130
+ <property name="jruby.compile.chainsize" value="500"/>
131
+ <property name="jruby.compile.lazyHandles" value="false"/>
132
+ <property name="jruby.compile.peephole" value="true"/>
133
+ </system-properties>
134
+ </appengine-web-app>
135
+ APPENGINE
136
+ end
137
+
138
+ def find_sdk
139
+ unless @sdk_path
140
+ @sdk_path = robot_config['appcfg']['sdk'] if robot_config['appcfg'] && robot_config['appcfg']['sdk'] # Points at main SDK dir.
141
+ @sdk_path ||= ENV['APPENGINE_JAVA_SDK'] # Points at main SDK dir.
142
+ unless @sdk_path
143
+ # Check everything in the PATH, which would point at the bin directory in the SDK.
144
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
145
+ if File.exists?(File.join(path, "appcfg.sh")) or File.exists?(File.join("appcfg.cmd"))
146
+ @sdk_path = File.dirname(path)
147
+ break
148
+ end
149
+ end
150
+ end
151
+ end
152
+ @sdk_path
153
+ end
154
+
155
+ end
156
+ end