rdmopensource-warbler 1.1.0

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.
Files changed (47) hide show
  1. data/Gemfile +11 -0
  2. data/History.txt +167 -0
  3. data/LICENSE.txt +26 -0
  4. data/Manifest.txt +48 -0
  5. data/README.txt +194 -0
  6. data/Rakefile +92 -0
  7. data/bin/warble +11 -0
  8. data/ext/Main.java +110 -0
  9. data/ext/WarblerWar.java +115 -0
  10. data/ext/WarblerWarService.java +17 -0
  11. data/lib/warbler.rb +37 -0
  12. data/lib/warbler/application.rb +67 -0
  13. data/lib/warbler/config.rb +349 -0
  14. data/lib/warbler/gems.rb +37 -0
  15. data/lib/warbler/runtime.rb +44 -0
  16. data/lib/warbler/task.rb +224 -0
  17. data/lib/warbler/version.rb +10 -0
  18. data/lib/warbler/war.rb +226 -0
  19. data/lib/warbler_war.jar +0 -0
  20. data/spec/sample/app/controllers/application.rb +15 -0
  21. data/spec/sample/app/helpers/application_helper.rb +3 -0
  22. data/spec/sample/config/boot.rb +109 -0
  23. data/spec/sample/config/database.yml +19 -0
  24. data/spec/sample/config/environment.rb +67 -0
  25. data/spec/sample/config/environments/development.rb +17 -0
  26. data/spec/sample/config/environments/production.rb +22 -0
  27. data/spec/sample/config/environments/test.rb +22 -0
  28. data/spec/sample/config/initializers/inflections.rb +10 -0
  29. data/spec/sample/config/initializers/mime_types.rb +5 -0
  30. data/spec/sample/config/initializers/new_rails_defaults.rb +15 -0
  31. data/spec/sample/config/routes.rb +41 -0
  32. data/spec/sample/lib/tasks/utils.rake +0 -0
  33. data/spec/sample/public/404.html +30 -0
  34. data/spec/sample/public/422.html +30 -0
  35. data/spec/sample/public/500.html +30 -0
  36. data/spec/sample/public/favicon.ico +0 -0
  37. data/spec/sample/public/index.html +274 -0
  38. data/spec/sample/public/robots.txt +5 -0
  39. data/spec/spec_helper.rb +44 -0
  40. data/spec/warbler/application_spec.rb +93 -0
  41. data/spec/warbler/config_spec.rb +112 -0
  42. data/spec/warbler/gems_spec.rb +40 -0
  43. data/spec/warbler/task_spec.rb +146 -0
  44. data/spec/warbler/war_spec.rb +441 -0
  45. data/warble.rb +121 -0
  46. data/web.xml.erb +32 -0
  47. metadata +202 -0
@@ -0,0 +1,92 @@
1
+ #--
2
+ # Copyright (c) 2010 Engine Yard, Inc.
3
+ # Copyright (c) 2007-2009 Sun Microsystems, Inc.
4
+ # This source code is available under the MIT license.
5
+ # See the file LICENSE.txt for details.
6
+ #++
7
+
8
+ begin
9
+ require 'bundler'
10
+ Bundler.setup
11
+ rescue LoadError
12
+ puts "Please install Bundler and run 'bundle install' to ensure you have all dependencies"
13
+ end
14
+
15
+ require 'spec/rake/spectask'
16
+ require 'spec/rake/verify_rcov'
17
+
18
+ MANIFEST = FileList["History.txt", "Manifest.txt", "README.txt", "Gemfile",
19
+ "LICENSE.txt", "Rakefile", "*.erb", "*.rb", "bin/*",
20
+ "ext/**/*", "lib/**/*", "spec/**/*.rb", "spec/sample/**/*.*"
21
+ ].to_a.reject{|f| f=~%r{spec/sample/(MANIFEST|link|web.xml)}}.sort.uniq
22
+
23
+ begin
24
+ File.open("Manifest.txt", "w") {|f| MANIFEST.each {|n| f << "#{n}\n"} }
25
+ require 'hoe'
26
+ require File.dirname(__FILE__) + '/lib/warbler/version'
27
+ hoe = Hoe.spec("warbler") do |p|
28
+ p.version = Warbler::VERSION
29
+ p.rubyforge_name = "caldersphere"
30
+ p.url = "http://caldersphere.rubyforge.org/warbler"
31
+ p.author = "Nick Sieger"
32
+ p.email = "nick@nicksieger.com"
33
+ p.summary = "Warbler chirpily constructs .war files of your Rails applications."
34
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
35
+ p.description = p.paragraphs_of('README.txt', 1...2).join("\n\n")
36
+ p.extra_deps += [['rake', '>= 0.8.7'], ['jruby-jars', '>= 1.4.0'], ['jruby-rack', '>= 1.0.0'], ['rubyzip', '>= 0.9.4']]
37
+ p.clean_globs += ['spec/sample/MANIFEST*', 'spec/sample/web.xml*']
38
+ end
39
+ hoe.spec.files = MANIFEST
40
+ hoe.spec.dependencies.delete_if { |dep| dep.name == "hoe" }
41
+ hoe.spec.rdoc_options += ["-SHN", "-f", "darkfish"]
42
+
43
+ task :gemspec do
44
+ File.open("#{hoe.name}.gemspec", "w") {|f| f << hoe.spec.to_ruby }
45
+ end
46
+ task :package => :gemspec
47
+ rescue LoadError
48
+ puts "You really need Hoe installed to be able to package this gem"
49
+ end
50
+
51
+ # Leave my tasks alone, Hoe
52
+ %w(default spec rcov).each do |task|
53
+ Rake::Task[task].prerequisites.clear
54
+ Rake::Task[task].actions.clear
55
+ end
56
+
57
+ Spec::Rake::SpecTask.new do |t|
58
+ t.spec_opts ||= []
59
+ t.spec_opts << "--options" << "spec/spec.opts"
60
+ end
61
+
62
+ Spec::Rake::SpecTask.new("spec:rcov") do |t|
63
+ t.spec_opts ||= []
64
+ t.spec_opts << "--options" << "spec/spec.opts"
65
+ t.rcov = true
66
+ end
67
+
68
+ RCov::VerifyTask.new(:rcov => "spec:rcov") do |t|
69
+ t.threshold = 100
70
+ end
71
+
72
+ task :default => :spec
73
+
74
+ begin
75
+ require 'ant'
76
+ directory "pkg/classes"
77
+ task :compile => "pkg/classes" do |t|
78
+ ant.javac :srcdir => "ext", :destdir => t.prerequisites.first,
79
+ :source => "1.5", :target => "1.5", :debug => true,
80
+ :classpath => "${java.class.path}:${sun.boot.class.path}"
81
+ end
82
+
83
+ task :jar => :compile do
84
+ ant.jar :basedir => "pkg/classes", :destfile => "lib/warbler_war.jar", :includes => "*.class"
85
+ end
86
+ rescue LoadError
87
+ task :jar do
88
+ puts "Run 'jar' with JRuby >= 1.5 to re-compile the java war booster"
89
+ end
90
+ end
91
+
92
+ task :package => :jar
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ #--
4
+ # Copyright (c) 2010 Engine Yard, Inc.
5
+ # Copyright (c) 2007-2009 Sun Microsystems, Inc.
6
+ # This source code is available under the MIT license.
7
+ # See the file LICENSE.txt for details.
8
+ #++
9
+
10
+ require 'warbler'
11
+ Warbler::Application.new.run
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Copyright (c) 2010 Engine Yard, Inc.
3
+ * This source code is available under the MIT license.
4
+ * See the file LICENSE.txt for details.
5
+ */
6
+
7
+ import java.net.URLClassLoader;
8
+ import java.net.URL;
9
+ import java.lang.reflect.Method;
10
+ import java.io.IOException;
11
+ import java.io.InputStream;
12
+ import java.io.File;
13
+ import java.io.FileOutputStream;
14
+ import java.util.Arrays;
15
+
16
+ public class Main implements Runnable {
17
+ public static final String MAIN = "/" + Main.class.getName().replace('.', '/') + ".class";
18
+ public static final String WINSTONE_JAR = "/WEB-INF/winstone.jar";
19
+
20
+ private String[] args;
21
+ private String path, warfile;
22
+ private boolean debug;
23
+ private File webroot;
24
+
25
+ public Main(String[] args) throws Exception {
26
+ this.args = args;
27
+ URL mainClass = getClass().getResource(MAIN);
28
+ this.path = mainClass.toURI().getSchemeSpecificPart();
29
+ this.warfile = mainClass.getFile().replace("!" + MAIN, "").replace("file:", "");
30
+ this.debug = isDebug();
31
+ this.webroot = File.createTempFile("winstone", "webroot");
32
+ this.webroot.delete();
33
+ this.webroot.mkdirs();
34
+ this.webroot = new File(this.webroot, new File(warfile).getName());
35
+ Runtime.getRuntime().addShutdownHook(new Thread(this));
36
+ }
37
+
38
+ private URL extractWinstone() throws Exception {
39
+ InputStream jarStream = new URL("jar:" + path.replace(MAIN, WINSTONE_JAR)).openStream();
40
+ File jarFile = File.createTempFile("winstone", ".jar");
41
+ jarFile.deleteOnExit();
42
+ FileOutputStream outStream = new FileOutputStream(jarFile);
43
+ try {
44
+ byte[] buf = new byte[4096];
45
+ int bytesRead = 0;
46
+ while ((bytesRead = jarStream.read(buf)) != -1) {
47
+ outStream.write(buf, 0, bytesRead);
48
+ }
49
+ } finally {
50
+ jarStream.close();
51
+ outStream.close();
52
+ }
53
+ debug("winstone.jar extracted to " + jarFile.getPath());
54
+ return jarFile.toURI().toURL();
55
+ }
56
+
57
+ private void launchWinstone(URL jar) throws Exception {
58
+ URLClassLoader loader = new URLClassLoader(new URL[] {jar});
59
+ Class klass = Class.forName("winstone.Launcher", true, loader);
60
+ Method main = klass.getDeclaredMethod("main", new Class[] {String[].class});
61
+ String[] newargs = new String[args.length + 2];
62
+ newargs[0] = "--warfile=" + warfile;
63
+ newargs[1] = "--webroot=" + webroot;
64
+ System.arraycopy(args, 0, newargs, 2, args.length);
65
+ debug("invoking Winstone with: " + Arrays.deepToString(newargs));
66
+ main.invoke(null, new Object[] {newargs});
67
+ }
68
+
69
+ private void start() throws Exception {
70
+ URL u = extractWinstone();
71
+ launchWinstone(u);
72
+ }
73
+
74
+ private void debug(String msg) {
75
+ if (debug) {
76
+ System.out.println(msg);
77
+ }
78
+ }
79
+
80
+ private void delete(File f) {
81
+ if (f.isDirectory()) {
82
+ File[] children = f.listFiles();
83
+ for (int i = 0; i < children.length; i++) {
84
+ delete(children[i]);
85
+ }
86
+ }
87
+ f.delete();
88
+ }
89
+
90
+ public void run() {
91
+ delete(webroot.getParentFile());
92
+ }
93
+
94
+ public static void main(String[] args) {
95
+ try {
96
+ new Main(args).start();
97
+ } catch (Exception e) {
98
+ System.err.println("error: " + e.toString());
99
+ if (isDebug()) {
100
+ e.printStackTrace();
101
+ }
102
+ System.exit(1);
103
+ }
104
+ }
105
+
106
+ private static boolean isDebug() {
107
+ return System.getProperty("warbler.debug") != null;
108
+ }
109
+ }
110
+
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Copyright (c) 2010 Engine Yard, Inc.
3
+ * This source code is available under the MIT license.
4
+ * See the file LICENSE.txt for details.
5
+ */
6
+
7
+ import java.io.Closeable;
8
+ import java.io.File;
9
+ import java.io.FileInputStream;
10
+ import java.io.FileOutputStream;
11
+ import java.io.IOException;
12
+ import java.util.zip.ZipEntry;
13
+ import java.util.zip.ZipOutputStream;
14
+
15
+ import org.jruby.Ruby;
16
+ import org.jruby.RubyArray;
17
+ import org.jruby.RubyHash;
18
+ import org.jruby.RubyModule;
19
+ import org.jruby.RubyString;
20
+ import org.jruby.anno.JRubyMethod;
21
+ import org.jruby.runtime.Block;
22
+ import org.jruby.runtime.ThreadContext;
23
+ import org.jruby.runtime.builtin.IRubyObject;
24
+ import org.jruby.util.JRubyFile;
25
+
26
+ public class WarblerWar {
27
+ public static void create(Ruby runtime) {
28
+ RubyModule task = runtime.getClassFromPath("Warbler::War");
29
+ task.defineAnnotatedMethods(WarblerWar.class);
30
+ }
31
+
32
+ @JRubyMethod
33
+ public static IRubyObject create_war(ThreadContext context, IRubyObject recv, IRubyObject war_path, IRubyObject entries) {
34
+ final Ruby runtime = recv.getRuntime();
35
+
36
+ if (!(entries instanceof RubyHash)) {
37
+ throw runtime.newArgumentError("expected a hash for the second argument");
38
+ }
39
+
40
+ RubyHash hash = (RubyHash) entries;
41
+ try {
42
+ FileOutputStream file = newFile(war_path);
43
+ try {
44
+ ZipOutputStream zip = new ZipOutputStream(file);
45
+ addEntries(context, zip, hash);
46
+ zip.finish();
47
+ } finally {
48
+ close(file);
49
+ }
50
+ } catch (IOException e) {
51
+ if (runtime.isDebug()) {
52
+ e.printStackTrace();
53
+ }
54
+ throw runtime.newIOErrorFromException(e);
55
+ }
56
+
57
+ return runtime.getNil();
58
+ }
59
+
60
+ private static void addEntries(ThreadContext context, ZipOutputStream zip, RubyHash entries) throws IOException {
61
+ RubyArray keys = entries.keys().sort(context, Block.NULL_BLOCK);
62
+ for (int i = 0; i < keys.getLength(); i++) {
63
+ IRubyObject key = keys.entry(i);
64
+ IRubyObject value = entries.op_aref(context, key);
65
+ addEntry(context, zip, key.convertToString().getUnicodeValue(), value);
66
+ }
67
+ }
68
+
69
+ private static void addEntry(ThreadContext context, ZipOutputStream zip, String entryName, IRubyObject value) throws IOException {
70
+ if (value.respondsTo("read")) {
71
+ RubyString str = (RubyString) value.callMethod(context, "read").checkStringType();
72
+ byte[] contents = str.getByteList().getUnsafeBytes();
73
+ zip.putNextEntry(new ZipEntry(entryName));
74
+ zip.write(contents);
75
+ } else {
76
+ File f;
77
+ if (value.isNil() || (f = getFile(value)).isDirectory()) {
78
+ zip.putNextEntry(new ZipEntry(entryName + "/"));
79
+ } else {
80
+ FileInputStream inFile = openFile(f);
81
+ try {
82
+ zip.putNextEntry(new ZipEntry(entryName));
83
+ byte[] buf = new byte[16384];
84
+ int bytesRead = -1;
85
+ while ((bytesRead = inFile.read(buf)) != -1) {
86
+ zip.write(buf, 0, bytesRead);
87
+ }
88
+ } finally {
89
+ close(inFile);
90
+ }
91
+ }
92
+ }
93
+ }
94
+
95
+ private static FileOutputStream newFile(IRubyObject war_path) throws IOException {
96
+ return new FileOutputStream(getFile(war_path));
97
+ }
98
+
99
+ private static FileInputStream openFile(File file) throws IOException {
100
+ return new FileInputStream(file);
101
+ }
102
+
103
+ private static File getFile(IRubyObject path) {
104
+ return JRubyFile.create(path.getRuntime().getCurrentDirectory(),
105
+ path.convertToString().getUnicodeValue());
106
+ }
107
+
108
+ private static void close(Closeable c) {
109
+ try {
110
+ c.close();
111
+ } catch (IOException e) {
112
+ }
113
+ }
114
+
115
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Copyright (c) 2010 Engine Yard, Inc.
3
+ * This source code is available under the MIT license.
4
+ * See the file LICENSE.txt for details.
5
+ */
6
+
7
+ import java.io.IOException;
8
+ import org.jruby.Ruby;
9
+ import org.jruby.runtime.load.BasicLibraryService;
10
+
11
+ public class WarblerWarService implements BasicLibraryService {
12
+ public boolean basicLoad(final Ruby runtime) throws IOException {
13
+ WarblerWar.create(runtime);
14
+ return true;
15
+ }
16
+ }
17
+
@@ -0,0 +1,37 @@
1
+ #--
2
+ # Copyright (c) 2010 Engine Yard, Inc.
3
+ # Copyright (c) 2007-2009 Sun Microsystems, Inc.
4
+ # This source code is available under the MIT license.
5
+ # See the file LICENSE.txt for details.
6
+ #++
7
+
8
+ # Warbler is a lightweight, flexible, Rake-based system for packaging your Rails apps
9
+ # into .war files.
10
+ module Warbler
11
+ WARBLER_HOME = File.expand_path(File.dirname(__FILE__) + '/..') unless defined?(WARBLER_HOME)
12
+
13
+ class << self
14
+ # An instance of Warbler::Application used by the +warble+ command.
15
+ attr_accessor :application
16
+ # Set Warbler.framework_detection to false to disable
17
+ # auto-detection based on application configuration.
18
+ attr_accessor :framework_detection
19
+ attr_writer :project_application
20
+ end
21
+
22
+ # Warbler loads the project Rakefile in a separate Rake application
23
+ # from the one where the Warbler tasks are run.
24
+ def self.project_application
25
+ application.load_project_rakefile if application
26
+ @project_application || Rake.application
27
+ end
28
+ self.framework_detection = true
29
+ end
30
+
31
+ require 'warbler/version'
32
+ require 'warbler/gems'
33
+ require 'warbler/config'
34
+ require 'warbler/war'
35
+ require 'warbler/task'
36
+ require 'warbler/application'
37
+ require 'warbler/runtime'
@@ -0,0 +1,67 @@
1
+ #--
2
+ # Copyright (c) 2010 Engine Yard, Inc.
3
+ # Copyright (c) 2007-2009 Sun Microsystems, Inc.
4
+ # This source code is available under the MIT license.
5
+ # See the file LICENSE.txt for details.
6
+ #++
7
+
8
+ require 'rake'
9
+
10
+ # Extension of Rake::Application that allows the +warble+ command to
11
+ # report its name properly and inject its own tasks without a
12
+ # Rakefile.
13
+ class Warbler::Application < Rake::Application
14
+ def initialize
15
+ super
16
+ Warbler.application = self
17
+ @project_loaded = false
18
+ end
19
+
20
+ # Sets the application name and loads Warbler's own tasks
21
+ def load_rakefile
22
+ @name = 'warble'
23
+
24
+ # Load the main warbler tasks
25
+ Warbler::Task.new
26
+
27
+ task :default => :war
28
+
29
+ desc "Generate a configuration file to customize your war"
30
+ task :config => "war:config"
31
+
32
+ desc "Install Warbler tasks in your Rails application"
33
+ task :pluginize => "war:pluginize"
34
+
35
+ desc "Feature: package gem repository inside a jar"
36
+ task :gemjar => "war:gemjar"
37
+
38
+ desc "Feature: make an executable archive"
39
+ task :executable => "war:executable"
40
+
41
+ desc "Display version of Warbler"
42
+ task :version => "war:version"
43
+ end
44
+
45
+ # Loads the project Rakefile in a separate application
46
+ def load_project_rakefile
47
+ return if @project_loaded
48
+ # Load any application rakefiles to aid in autodetecting applications
49
+ app = Warbler.project_application = Rake::Application.new
50
+ Rake.application = app
51
+ Rake::Application::DEFAULT_RAKEFILES.each do |rf|
52
+ if File.exist?(rf)
53
+ load rf
54
+ break
55
+ end
56
+ end
57
+ Rake.application = self
58
+ @project_loaded = true
59
+ end
60
+
61
+ # Run the application: The equivalent code for the +warble+ command
62
+ # is simply <tt>Warbler::Application.new.run</tt>.
63
+ def run
64
+ Rake.application = self
65
+ super
66
+ end
67
+ end