rdmopensource-warbler 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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