lucidimagination-warbler 1.3.2.dev

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. data/Gemfile +16 -0
  2. data/History.txt +217 -0
  3. data/LICENSE.txt +26 -0
  4. data/Manifest.txt +92 -0
  5. data/README.txt +255 -0
  6. data/Rakefile +103 -0
  7. data/bin/warble +11 -0
  8. data/ext/JarMain.java +148 -0
  9. data/ext/WarMain.java +112 -0
  10. data/ext/WarblerJar.java +182 -0
  11. data/ext/WarblerJarService.java +18 -0
  12. data/lib/warbler.rb +33 -0
  13. data/lib/warbler/application.rb +86 -0
  14. data/lib/warbler/config.rb +223 -0
  15. data/lib/warbler/gems.rb +37 -0
  16. data/lib/warbler/jar.rb +253 -0
  17. data/lib/warbler/task.rb +183 -0
  18. data/lib/warbler/templates/bundler.erb +3 -0
  19. data/lib/warbler/templates/config.erb +1 -0
  20. data/lib/warbler/templates/jar.erb +5 -0
  21. data/lib/warbler/templates/rack.erb +1 -0
  22. data/lib/warbler/templates/rails.erb +1 -0
  23. data/lib/warbler/templates/war.erb +1 -0
  24. data/lib/warbler/traits.rb +107 -0
  25. data/lib/warbler/traits/bundler.rb +104 -0
  26. data/lib/warbler/traits/gemspec.rb +59 -0
  27. data/lib/warbler/traits/jar.rb +56 -0
  28. data/lib/warbler/traits/merb.rb +35 -0
  29. data/lib/warbler/traits/nogemspec.rb +42 -0
  30. data/lib/warbler/traits/rack.rb +33 -0
  31. data/lib/warbler/traits/rails.rb +62 -0
  32. data/lib/warbler/traits/war.rb +197 -0
  33. data/lib/warbler/version.rb +10 -0
  34. data/lib/warbler/war.rb +8 -0
  35. data/lib/warbler_jar.jar +0 -0
  36. data/spec/drb_helper.rb +41 -0
  37. data/spec/sample_bundler/Gemfile.lock +10 -0
  38. data/spec/sample_bundler/config.ru +0 -0
  39. data/spec/sample_jar/History.txt +6 -0
  40. data/spec/sample_jar/Manifest.txt +8 -0
  41. data/spec/sample_jar/README.txt +30 -0
  42. data/spec/sample_jar/lib/sample_jar.rb +6 -0
  43. data/spec/sample_jar/sample_jar.gemspec +40 -0
  44. data/spec/sample_jar/test/test_sample_jar.rb +8 -0
  45. data/spec/sample_war/app/controllers/application.rb +15 -0
  46. data/spec/sample_war/app/helpers/application_helper.rb +3 -0
  47. data/spec/sample_war/config/boot.rb +109 -0
  48. data/spec/sample_war/config/database.yml +19 -0
  49. data/spec/sample_war/config/environment.rb +67 -0
  50. data/spec/sample_war/config/environments/development.rb +17 -0
  51. data/spec/sample_war/config/environments/production.rb +25 -0
  52. data/spec/sample_war/config/environments/test.rb +22 -0
  53. data/spec/sample_war/config/initializers/inflections.rb +10 -0
  54. data/spec/sample_war/config/initializers/mime_types.rb +5 -0
  55. data/spec/sample_war/config/initializers/new_rails_defaults.rb +15 -0
  56. data/spec/sample_war/config/routes.rb +41 -0
  57. data/spec/sample_war/lib/tasks/utils.rake +0 -0
  58. data/spec/sample_war/public/404.html +30 -0
  59. data/spec/sample_war/public/422.html +30 -0
  60. data/spec/sample_war/public/500.html +30 -0
  61. data/spec/sample_war/public/favicon.ico +0 -0
  62. data/spec/sample_war/public/index.html +274 -0
  63. data/spec/sample_war/public/robots.txt +5 -0
  64. data/spec/spec_helper.rb +112 -0
  65. data/spec/warbler/application_spec.rb +95 -0
  66. data/spec/warbler/bundler_spec.rb +136 -0
  67. data/spec/warbler/config_spec.rb +130 -0
  68. data/spec/warbler/gems_spec.rb +40 -0
  69. data/spec/warbler/jar_spec.rb +718 -0
  70. data/spec/warbler/task_spec.rb +170 -0
  71. data/spec/warbler/traits_spec.rb +17 -0
  72. data/spec/warbler/war_spec.rb +14 -0
  73. data/warble.rb +142 -0
  74. data/web.xml.erb +32 -0
  75. metadata +198 -0
@@ -0,0 +1,103 @@
1
+ #--
2
+ # Copyright (c) 2010-2011 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/setup'
10
+ rescue LoadError
11
+ puts "Please install Bundler and run 'bundle install' to ensure you have all dependencies"
12
+ end
13
+
14
+ require 'spec/rake/spectask'
15
+ require 'spec/rake/verify_rcov'
16
+
17
+ MANIFEST = FileList["History.txt", "Manifest.txt", "README.txt", "Gemfile",
18
+ "LICENSE.txt", "Rakefile", "*.erb", "*.rb", "bin/*",
19
+ "ext/**/*", "lib/**/*", "spec/**/*.rb", "spec/sample*/**/*.*"
20
+ ].to_a.reject{|f| f=~%r{spec/sample/(MANIFEST|link|web.xml)}}.sort.uniq
21
+
22
+ begin
23
+ File.open("Manifest.txt", "wb") {|f| MANIFEST.each {|n| f << "#{n}\n"} }
24
+ require 'hoe'
25
+ require File.dirname(__FILE__) + '/lib/warbler/version'
26
+ Hoe.plugin :rubyforge
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 += %w(MANIFEST web.xml init.rb).map{|f| "spec/sample*/#{f}*" }
38
+ end
39
+ hoe.spec.files = MANIFEST
40
+ hoe.spec.rdoc_options += ["-SHN", "-f", "darkfish"]
41
+
42
+ task :gemspec do
43
+ File.open("#{hoe.name}.gemspec", "w") {|f| f << hoe.spec.to_ruby }
44
+ end
45
+ task :package => :gemspec
46
+ rescue LoadError
47
+ puts "You really need Hoe installed to be able to package this gem"
48
+ end
49
+
50
+ # Leave my tasks alone, Hoe
51
+ %w(default spec rcov).each do |task|
52
+ Rake::Task[task].prerequisites.clear
53
+ Rake::Task[task].actions.clear
54
+ end
55
+
56
+ Spec::Rake::SpecTask.new do |t|
57
+ t.spec_opts ||= []
58
+ t.spec_opts << "--options" << "spec/spec.opts"
59
+ end
60
+
61
+ Spec::Rake::SpecTask.new("spec:rcov") do |t|
62
+ t.spec_opts ||= []
63
+ t.spec_opts << "--options" << "spec/spec.opts"
64
+ t.rcov_opts ||= []
65
+ t.rcov_opts << "-x" << "/gems/"
66
+ t.rcov = true
67
+ end
68
+
69
+ RCov::VerifyTask.new(:rcov => "spec:rcov") do |t|
70
+ t.threshold = 100
71
+ end
72
+
73
+ task :default => :spec
74
+
75
+ desc "Compile and jar the Warbler Java helper classes"
76
+ begin
77
+ require 'ant'
78
+ task :jar => :compile do
79
+ ant.jar :basedir => "pkg/classes", :destfile => "lib/warbler_jar.jar", :includes => "*.class"
80
+ end
81
+
82
+ directory "pkg/classes"
83
+ task :compile => "pkg/classes" do |t|
84
+ ant.javac :srcdir => "ext", :destdir => t.prerequisites.first,
85
+ :source => "1.5", :target => "1.5", :debug => true,
86
+ :classpath => "${java.class.path}:${sun.boot.class.path}",
87
+ :includeantRuntime => false
88
+ end
89
+ rescue LoadError
90
+ task :jar do
91
+ puts "Run 'jar' with JRuby >= 1.5 to re-compile the java jar booster"
92
+ end
93
+ end
94
+
95
+ # Make sure jar gets compiled before the gem is built
96
+ task Rake::Task['gem'].prerequisites.first => :jar
97
+
98
+ task :warbler_jar => 'pkg' do
99
+ ruby "-rubygems", "-Ilib", "-S", "bin/warble"
100
+ mv "warbler.jar", "pkg/warbler-#{Warbler::VERSION}.jar"
101
+ end
102
+
103
+ task :package => :warbler_jar
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ #--
4
+ # Copyright (c) 2010-2011 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,148 @@
1
+ /**
2
+ * Copyright (c) 2010-2011 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
+ import java.io.File;
9
+ import java.io.FileOutputStream;
10
+ import java.io.InputStream;
11
+ import java.lang.reflect.Method;
12
+ import java.net.URL;
13
+ import java.net.URLClassLoader;
14
+ import java.util.ArrayList;
15
+ import java.util.Arrays;
16
+ import java.util.Enumeration;
17
+ import java.util.List;
18
+ import java.util.jar.JarEntry;
19
+ import java.util.jar.JarFile;
20
+
21
+ public class JarMain implements Runnable {
22
+ public static final String MAIN = "/" + JarMain.class.getName().replace('.', '/') + ".class";
23
+
24
+ private String[] args;
25
+ private String path, jarfile;
26
+ private boolean debug;
27
+ private File extractRoot;
28
+
29
+ public JarMain(String[] args) throws Exception {
30
+ this.args = args;
31
+ URL mainClass = getClass().getResource(MAIN);
32
+ this.path = mainClass.toURI().getSchemeSpecificPart();
33
+ this.jarfile = this.path.replace("!" + MAIN, "").replace("file:", "");
34
+ this.debug = isDebug();
35
+ this.extractRoot = File.createTempFile("jruby", "extract");
36
+ this.extractRoot.delete();
37
+ this.extractRoot.mkdirs();
38
+ Runtime.getRuntime().addShutdownHook(new Thread(this));
39
+ }
40
+
41
+ private URL[] extractJRuby() throws Exception {
42
+ JarFile jf = new JarFile(this.jarfile);
43
+ List<String> jarNames = new ArrayList<String>();
44
+ for (Enumeration<JarEntry> eje = jf.entries(); eje.hasMoreElements(); ) {
45
+ String name = eje.nextElement().getName();
46
+ if (name.startsWith("META-INF/lib") && name.endsWith(".jar")) {
47
+ jarNames.add("/" + name);
48
+ }
49
+ }
50
+
51
+ List<URL> urls = new ArrayList<URL>();
52
+ for (String name : jarNames) {
53
+ urls.add(extractJar(name));
54
+ }
55
+
56
+ return (URL[]) urls.toArray(new URL[urls.size()]);
57
+ }
58
+
59
+ private URL extractJar(String jarpath) throws Exception {
60
+ InputStream jarStream = new URL("jar:" + path.replace(MAIN, jarpath)).openStream();
61
+ String jarname = jarpath.substring(jarpath.lastIndexOf("/") + 1, jarpath.lastIndexOf("."));
62
+ File jarFile = new File(extractRoot, jarname + ".jar");
63
+ jarFile.deleteOnExit();
64
+ FileOutputStream outStream = new FileOutputStream(jarFile);
65
+ try {
66
+ byte[] buf = new byte[65536];
67
+ int bytesRead = 0;
68
+ while ((bytesRead = jarStream.read(buf)) != -1) {
69
+ outStream.write(buf, 0, bytesRead);
70
+ }
71
+ } finally {
72
+ jarStream.close();
73
+ outStream.close();
74
+ }
75
+ debug(jarname + ".jar extracted to " + jarFile.getPath());
76
+ return jarFile.toURI().toURL();
77
+ }
78
+
79
+ private int launchJRuby(URL[] jars) throws Exception {
80
+ System.setProperty("org.jruby.embed.class.path", "");
81
+ URLClassLoader loader = new URLClassLoader(jars);
82
+ Class scriptingContainerClass = Class.forName("org.jruby.embed.ScriptingContainer", true, loader);
83
+ Object scriptingContainer = scriptingContainerClass.newInstance();
84
+
85
+ Method argv = scriptingContainerClass.getDeclaredMethod("setArgv", new Class[] {String[].class});
86
+ argv.invoke(scriptingContainer, new Object[] {args});
87
+ Method setClassLoader = scriptingContainerClass.getDeclaredMethod("setClassLoader", new Class[] {ClassLoader.class});
88
+ setClassLoader.invoke(scriptingContainer, new Object[] {loader});
89
+ debug("invoking " + jarfile + " with: " + Arrays.deepToString(args));
90
+
91
+ Method runScriptlet = scriptingContainerClass.getDeclaredMethod("runScriptlet", new Class[] {String.class});
92
+ return ((Number) runScriptlet.invoke(scriptingContainer, new Object[] {
93
+ "begin\n" +
94
+ "require 'META-INF/init.rb'\n" +
95
+ "require 'META-INF/main.rb'\n" +
96
+ "0\n" +
97
+ "rescue SystemExit => e\n" +
98
+ "e.status\n" +
99
+ "end"
100
+ })).intValue();
101
+ }
102
+
103
+ private int start() throws Exception {
104
+ URL[] u = extractJRuby();
105
+ return launchJRuby(u);
106
+ }
107
+
108
+ private void debug(String msg) {
109
+ if (debug) {
110
+ System.out.println(msg);
111
+ }
112
+ }
113
+
114
+ private void delete(File f) {
115
+ if (f.isDirectory()) {
116
+ File[] children = f.listFiles();
117
+ for (int i = 0; i < children.length; i++) {
118
+ delete(children[i]);
119
+ }
120
+ }
121
+ f.delete();
122
+ }
123
+
124
+ public void run() {
125
+ delete(extractRoot);
126
+ }
127
+
128
+ public static void main(String[] args) {
129
+ try {
130
+ int exit = new JarMain(args).start();
131
+ System.exit(exit);
132
+ } catch (Exception e) {
133
+ Throwable t = e;
134
+ while (t.getCause() != null && t.getCause() != t) {
135
+ t = t.getCause();
136
+ }
137
+
138
+ if (isDebug()) {
139
+ t.printStackTrace();
140
+ }
141
+ System.exit(1);
142
+ }
143
+ }
144
+
145
+ private static boolean isDebug() {
146
+ return System.getProperty("warbler.debug") != null;
147
+ }
148
+ }
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Copyright (c) 2010-2011 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
+ import java.net.URLClassLoader;
9
+ import java.net.URL;
10
+ import java.lang.reflect.Method;
11
+ import java.io.IOException;
12
+ import java.io.InputStream;
13
+ import java.io.File;
14
+ import java.io.FileOutputStream;
15
+ import java.util.Arrays;
16
+
17
+ public class WarMain implements Runnable {
18
+ public static final String MAIN = "/" + WarMain.class.getName().replace('.', '/') + ".class";
19
+ public static final String WINSTONE_JAR = "/WEB-INF/winstone.jar";
20
+
21
+ private String[] args;
22
+ private String path, warfile;
23
+ private boolean debug;
24
+ private File webroot;
25
+
26
+ public WarMain(String[] args) throws Exception {
27
+ this.args = args;
28
+ URL mainClass = getClass().getResource(MAIN);
29
+ this.path = mainClass.toURI().getSchemeSpecificPart();
30
+ this.warfile = this.path.replace("!" + MAIN, "").replace("file:", "");
31
+ this.debug = isDebug();
32
+ this.webroot = File.createTempFile("winstone", "webroot");
33
+ this.webroot.delete();
34
+ this.webroot.mkdirs();
35
+ this.webroot = new File(this.webroot, new File(warfile).getName());
36
+ Runtime.getRuntime().addShutdownHook(new Thread(this));
37
+ }
38
+
39
+ private URL extractWinstone() throws Exception {
40
+ InputStream jarStream = new URL("jar:" + path.replace(MAIN, WINSTONE_JAR)).openStream();
41
+ File jarFile = File.createTempFile("winstone", ".jar");
42
+ jarFile.deleteOnExit();
43
+ FileOutputStream outStream = new FileOutputStream(jarFile);
44
+ try {
45
+ byte[] buf = new byte[4096];
46
+ int bytesRead = 0;
47
+ while ((bytesRead = jarStream.read(buf)) != -1) {
48
+ outStream.write(buf, 0, bytesRead);
49
+ }
50
+ } finally {
51
+ jarStream.close();
52
+ outStream.close();
53
+ }
54
+ debug("winstone.jar extracted to " + jarFile.getPath());
55
+ return jarFile.toURI().toURL();
56
+ }
57
+
58
+ private void launchWinstone(URL jar) throws Exception {
59
+ URLClassLoader loader = new URLClassLoader(new URL[] {jar});
60
+ Class klass = Class.forName("winstone.Launcher", true, loader);
61
+ Method main = klass.getDeclaredMethod("main", new Class[] {String[].class});
62
+ String[] newargs = new String[args.length + 3];
63
+ newargs[0] = "--warfile=" + warfile;
64
+ newargs[1] = "--webroot=" + webroot;
65
+ newargs[2] = "--directoryListings=false";
66
+ System.arraycopy(args, 0, newargs, 3, args.length);
67
+ debug("invoking Winstone with: " + Arrays.deepToString(newargs));
68
+ main.invoke(null, new Object[] {newargs});
69
+ }
70
+
71
+ private void start() throws Exception {
72
+ URL u = extractWinstone();
73
+ launchWinstone(u);
74
+ }
75
+
76
+ private void debug(String msg) {
77
+ if (debug) {
78
+ System.out.println(msg);
79
+ }
80
+ }
81
+
82
+ private void delete(File f) {
83
+ if (f.isDirectory()) {
84
+ File[] children = f.listFiles();
85
+ for (int i = 0; i < children.length; i++) {
86
+ delete(children[i]);
87
+ }
88
+ }
89
+ f.delete();
90
+ }
91
+
92
+ public void run() {
93
+ delete(webroot.getParentFile());
94
+ }
95
+
96
+ public static void main(String[] args) {
97
+ try {
98
+ new WarMain(args).start();
99
+ } catch (Exception e) {
100
+ System.err.println("error: " + e.toString());
101
+ if (isDebug()) {
102
+ e.printStackTrace();
103
+ }
104
+ System.exit(1);
105
+ }
106
+ }
107
+
108
+ private static boolean isDebug() {
109
+ return System.getProperty("warbler.debug") != null;
110
+ }
111
+ }
112
+
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Copyright (c) 2010-2011 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
+ import java.io.Closeable;
9
+ import java.io.File;
10
+ import java.io.FileInputStream;
11
+ import java.io.FileNotFoundException;
12
+ import java.io.FileOutputStream;
13
+ import java.io.IOException;
14
+ import java.io.InputStream;
15
+ import java.util.regex.Matcher;
16
+ import java.util.regex.Pattern;
17
+ import java.util.zip.ZipEntry;
18
+ import java.util.zip.ZipInputStream;
19
+ import java.util.zip.ZipOutputStream;
20
+
21
+ import org.jruby.Ruby;
22
+ import org.jruby.RubyArray;
23
+ import org.jruby.RubyHash;
24
+ import org.jruby.RubyModule;
25
+ import org.jruby.RubyString;
26
+ import org.jruby.anno.JRubyMethod;
27
+ import org.jruby.runtime.Block;
28
+ import org.jruby.runtime.ThreadContext;
29
+ import org.jruby.runtime.builtin.IRubyObject;
30
+ import org.jruby.util.ByteList;
31
+ import org.jruby.util.JRubyFile;
32
+
33
+ public class WarblerJar {
34
+ public static void create(Ruby runtime) {
35
+ RubyModule task = runtime.getClassFromPath("Warbler::Jar");
36
+ task.defineAnnotatedMethods(WarblerJar.class);
37
+ }
38
+
39
+ @JRubyMethod
40
+ public static IRubyObject create_jar(ThreadContext context, IRubyObject recv, IRubyObject jar_path, IRubyObject entries) {
41
+ final Ruby runtime = recv.getRuntime();
42
+
43
+ if (!(entries instanceof RubyHash)) {
44
+ throw runtime.newArgumentError("expected a hash for the second argument");
45
+ }
46
+
47
+ RubyHash hash = (RubyHash) entries;
48
+ try {
49
+ FileOutputStream file = newFile(jar_path);
50
+ try {
51
+ ZipOutputStream zip = new ZipOutputStream(file);
52
+ addEntries(context, zip, hash);
53
+ zip.finish();
54
+ } finally {
55
+ close(file);
56
+ }
57
+ } catch (IOException e) {
58
+ if (runtime.isDebug()) {
59
+ e.printStackTrace();
60
+ }
61
+ throw runtime.newIOErrorFromException(e);
62
+ }
63
+
64
+ return runtime.getNil();
65
+ }
66
+
67
+ @JRubyMethod
68
+ public static IRubyObject entry_in_jar(ThreadContext context, IRubyObject recv, IRubyObject jar_path, IRubyObject entry) {
69
+ final Ruby runtime = recv.getRuntime();
70
+ try {
71
+ InputStream entryStream = getStream(jar_path.convertToString().getUnicodeValue(),
72
+ entry.convertToString().getUnicodeValue());
73
+ try {
74
+ byte[] buf = new byte[16384];
75
+ ByteList blist = new ByteList();
76
+ int bytesRead = -1;
77
+ while ((bytesRead = entryStream.read(buf)) != -1) {
78
+ blist.append(buf, 0, bytesRead);
79
+ }
80
+ IRubyObject stringio = runtime.getModule("StringIO");
81
+ return stringio.callMethod(context, "new", runtime.newString(blist));
82
+ } finally {
83
+ close(entryStream);
84
+ }
85
+ } catch (IOException e) {
86
+ if (runtime.isDebug()) {
87
+ e.printStackTrace();
88
+ }
89
+ throw runtime.newIOErrorFromException(e);
90
+ }
91
+ }
92
+
93
+ private static void addEntries(ThreadContext context, ZipOutputStream zip, RubyHash entries) throws IOException {
94
+ RubyArray keys = entries.keys().sort(context, Block.NULL_BLOCK);
95
+ for (int i = 0; i < keys.getLength(); i++) {
96
+ IRubyObject key = keys.entry(i);
97
+ IRubyObject value = entries.op_aref(context, key);
98
+ addEntry(context, zip, key.convertToString().getUnicodeValue(), value);
99
+ }
100
+ }
101
+
102
+ private static void addEntry(ThreadContext context, ZipOutputStream zip, String entryName, IRubyObject value) throws IOException {
103
+ if (value.respondsTo("read")) {
104
+ RubyString str = (RubyString) value.callMethod(context, "read").checkStringType();
105
+ byte[] contents = str.getByteList().getUnsafeBytes();
106
+ zip.putNextEntry(new ZipEntry(entryName));
107
+ zip.write(contents);
108
+ } else {
109
+ File f;
110
+ if (value.isNil() || (f = getFile(value)).isDirectory()) {
111
+ zip.putNextEntry(new ZipEntry(entryName + "/"));
112
+ } else {
113
+ String path = f.getPath();
114
+ if (!f.exists()) {
115
+ path = value.convertToString().getUnicodeValue();
116
+ }
117
+
118
+ InputStream inFile = getStream(path, null);
119
+ try {
120
+ zip.putNextEntry(new ZipEntry(entryName));
121
+ byte[] buf = new byte[16384];
122
+ int bytesRead = -1;
123
+ while ((bytesRead = inFile.read(buf)) != -1) {
124
+ zip.write(buf, 0, bytesRead);
125
+ }
126
+ } finally {
127
+ close(inFile);
128
+ }
129
+ }
130
+ }
131
+ }
132
+
133
+ private static FileOutputStream newFile(IRubyObject jar_path) throws IOException {
134
+ return new FileOutputStream(getFile(jar_path));
135
+ }
136
+
137
+ private static File getFile(IRubyObject path) {
138
+ return JRubyFile.create(path.getRuntime().getCurrentDirectory(),
139
+ path.convertToString().getUnicodeValue());
140
+ }
141
+
142
+ private static void close(Closeable c) {
143
+ try {
144
+ c.close();
145
+ } catch (Exception e) {
146
+ }
147
+ }
148
+
149
+ private static Pattern PROTOCOL = Pattern.compile("^[a-z][a-z0-9]+:");
150
+
151
+ private static InputStream getStream(String jar, String entry) throws IOException {
152
+ Matcher m = PROTOCOL.matcher(jar);
153
+ while (m.find()) {
154
+ jar = jar.substring(m.end());
155
+ m = PROTOCOL.matcher(jar);
156
+ }
157
+
158
+ String[] path = jar.split("!/");
159
+ InputStream stream = new FileInputStream(path[0]);
160
+ for (int i = 1; i < path.length; i++) {
161
+ stream = entryInJar(stream, path[i]);
162
+ }
163
+
164
+ if (entry == null) {
165
+ return stream;
166
+ }
167
+
168
+ return entryInJar(stream, entry);
169
+ }
170
+
171
+ private static InputStream entryInJar(InputStream jar, String entry) throws IOException {
172
+ ZipInputStream jstream = new ZipInputStream(jar);
173
+ ZipEntry zentry = null;
174
+ while ((zentry = jstream.getNextEntry()) != null) {
175
+ if (zentry.getName().equals(entry)) {
176
+ return jstream;
177
+ }
178
+ jstream.closeEntry();
179
+ }
180
+ throw new FileNotFoundException("entry '" + entry + "' not found in " + jar);
181
+ }
182
+ }