#!/usr/bin/env ruby # this line prevents other db adapters from being loaded (oci8 was # causing some pain.) unless Object.const_defined? :RAILS_CONNECTION_ADAPTERS RAILS_CONNECTION_ADAPTERS = [] end RAILS_CONNECTION_ADAPTERS.replace %w[sqlite] require 'delegate' require 'optparse' require 'stringio' require 'rubygems' require 'camping' host = '0.0.0.0' port = 3301 db = nil homes = [] homes << File.join( ENV['HOME'], '.camping.db' ) if ENV['HOME'] homes << File.join( ENV['APPDATA'], 'Camping.db' ) if ENV['APPDATA'] homes.each do |db| break if File.exists?( db ) end opts = OptionParser.new do |opts| opts.banner = "Usage: camping app1.rb, app2.rb..." opts.define_head "#{File.basename($0)}, the microframework ON-button for ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]" opts.separator "" opts.separator "Specific options:" opts.on("-h", "--host HOSTNAME", "Host for web server to bind to (default is all IPs)") do |h| host = h end opts.on("-p", "--port NUM", "Port for web server (defaults to #{port})") do |p| port = p end opts.on("-d", "--database FILE", "Database file (defaults to #{db})") do |d| db = d end opts.separator "" opts.separator "Common options:" # No argument, shows at tail. This will print an options summary. # Try it and see! opts.on_tail("-h", "--help", "Show this message") do puts opts exit end # Another typical switch to print the version. opts.on_tail("--version", "Show version") do class << Gem; attr_accessor :loaded_specs; end puts Gem.loaded_specs['camping'].version exit end end opts.parse! ARGV if ARGV.length < 1 puts opts exit end Camping::Models::Base.establish_connection :adapter => 'sqlite3', :database => db class CampingReloader attr_accessor :klass, :mtime, :mount def initialize(script) @script = script @mount = File.basename(script, '.rb') load_app end def load_app @mtime = File.mtime(@script) title = File.basename(@script)[/^(\w+)/,1] begin load @script rescue Exception => e puts "!! trouble loading #{title}: [#{e.class}] #{e.message}" @klass = nil return end @klass = Object.const_get(Object.constants.grep(/^#{title}$/i)[0]) rescue nil unless @klass.const_defined? :C puts "!! trouble loading #{title}: not a Camping app" @klass = nil return end @klass.create if @klass.respond_to? :create @klass end # Load the script, locate the module def reload_app newtime = File.mtime( @script ) return if @klass and @mtime and newtime <= @mtime k = @klass Object.instance_eval { remove_const k.name } if k load_app end def run(*a) reload_app if @klass @klass.run(*a) else Camping.run(*a) end end def view_source File.read(@script) end end apps = ARGV.map { |script| CampingReloader.new(script) } def apps.index_page welcome = "You are Camping" apps = self b = Markaby::Builder.new({}, {}) b = b.instance_eval do html do head do title welcome style <<-END, :type => 'text/css' body { font-family: verdana, arial, sans-serif; padding: 10px 40px; margin: 0; } h1, h2, h3, h4, h5, h6 { font-family: utopia, georgia, serif; } END end body do h1 welcome p %{Good day. These are the Camping apps you've mounted.} ul do apps.each do |app| next unless app.klass li do h3(:style => "display: inline") { a app.klass.name, :href => "/#{app.mount}" } small { text " / " ; a "View Source", :href => "/code/#{app.mount}" } end end end end end end b.to_s end begin require 'mongrel' require 'mongrel/camping' class IndexHandler < Mongrel::HttpHandler def initialize(apps) @apps = apps end def process(req, res) res.start(200) do |head, out| out << @apps.index_page end end end class ViewSource < Mongrel::HttpHandler def initialize(app) @app = app end def process(req, res) res.start(200) do |head, out| head['Content-Type'] = 'text/plain' out << @app.view_source end end end config = Mongrel::Configurator.new :host => host do listener :port => port do apps.each do |app| uri "/#{app.mount}", :handler => Mongrel::Camping::CampingHandler.new(app) uri "/code/#{app.mount}", :handler => ViewSource.new(app) end uri "/", :handler => IndexHandler.new(apps) uri "/favicon.ico", :handler => Mongrel::Error404Handler.new("") trap("INT") { stop } run end end config.join rescue LoadError require 'webrick/httpserver' require 'camping/webrick' # Mount the root s = WEBrick::HTTPServer.new(:BindAddress => host, :Port => port) apps.each do |app| s.mount "/#{app.mount}", WEBrick::CampingHandler, app s.mount_proc("/code/#{app.mount}") do |req, resp| resp['Content-Type'] = 'text/plain' resp.body = app.view_source end end s.mount_proc("/") { |req, resp| resp.body = apps.index_page } # Server up trap(:INT) do s.shutdown end s.start end