rubylet-rack 2.0.0.pre1-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Common Ground Publishing
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 2.0.0.pre1
@@ -0,0 +1,5 @@
1
+ require 'rubylet/rack/dechunking_body'
2
+ require 'rubylet/rack/errors'
3
+ require 'rubylet/rack/ext'
4
+ require 'rubylet/rack/rewindable_io'
5
+ require 'rubylet/rack/session/container_store'
@@ -0,0 +1,45 @@
1
+ module Rubylet
2
+ module Rack
3
+ # Rails and possibly others manually set 'Transfer-Encoding:
4
+ # chunked' and then send the body as chunks. Java servlet
5
+ # environment expects the server to handle chunking as needed
6
+ # (e.g. when a response overflows the buffer and must be flushed to
7
+ # the client before the servlet has closed the stream).
8
+ #
9
+ # This class makes the rather large assumption that {body#each}
10
+ # iterates through the chunks, so we don't actually do much parsing.
11
+ #
12
+ # FIXME: ignores encoding?
13
+ class DechunkingBody
14
+ EOL = "\r\n".freeze
15
+
16
+ CHUNK_START = Regexp.compile /^((\h+)#{Regexp.quote(EOL)})/
17
+
18
+ def initialize(body)
19
+ @body = body
20
+ end
21
+
22
+ def each
23
+ @body.each do |chunk|
24
+ yield chunk_to_part(chunk)
25
+ end
26
+ end
27
+
28
+ def close
29
+ @body.close
30
+ end
31
+
32
+ private
33
+
34
+ def chunk_to_part(chunk)
35
+ if chunk =~ CHUNK_START
36
+ chunk_start = $1.bytesize
37
+ chunk_length = $2.to_i(16)
38
+ chunk.byteslice(chunk_start, chunk_length)
39
+ else
40
+ chunk
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,25 @@
1
+ # Implements the rack.errors interface, logging everything via
2
+ # ServletContext#log
3
+ module Rubylet
4
+ module Rack
5
+ class Errors
6
+ def initialize(context)
7
+ @context = context
8
+ end
9
+
10
+ def puts(obj)
11
+ write(obj.to_s)
12
+ end
13
+
14
+ def write(str)
15
+ @context.log(str)
16
+ end
17
+
18
+ # A no-op for ServletContext#log
19
+ def flush; end
20
+
21
+ # Spec says this must never be called
22
+ def close; end
23
+ end
24
+ end
25
+ end
Binary file
@@ -0,0 +1,40 @@
1
+ require 'rubylet/rack/errors'
2
+
3
+ # TODO: should this wrap slf4j or something? Or is it typically overridden
4
+ # by the rack application?
5
+ module Rubylet
6
+ module Rack
7
+ class Logger < Rubylet::Errors
8
+
9
+ def info(message = nil, &block)
10
+ log(:info, message, &block)
11
+ end
12
+
13
+ def debug(message = nil, &block)
14
+ log(:debug, message, &block)
15
+ end
16
+
17
+ def warn(message = nil, &block)
18
+ log(:warn, message, &block)
19
+ end
20
+
21
+ def error(message = nil, &block)
22
+ log(:error, message, &block)
23
+ end
24
+
25
+ def fatal(message = nil, &block)
26
+ log(:fatal, message, &block)
27
+ end
28
+
29
+ def log(level, message = nil, &block)
30
+ msg = if message
31
+ message
32
+ elsif block_given?
33
+ yield
34
+ end
35
+
36
+ write("#{level.to_s.upcase}: #{msg}")
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,80 @@
1
+ require 'tempfile'
2
+
3
+ # A memory/file IO buffer. Data will be written to a memory buffer up
4
+ # to a limit, after which a file buffer is used. Supports Rack input
5
+ # stream operations. Not threadsafe.
6
+ module Rubylet::Rack
7
+ class MemFileIO
8
+ DEFAULT_LIMIT = 4096 * 4
9
+
10
+ # @param [Integer] limit the max size of the first (memory) buffer
11
+ def initialize(limit = DEFAULT_LIMIT)
12
+ @limit = limit
13
+ @mem = StringIO.new
14
+ @file = nil
15
+ end
16
+
17
+ def puts(str)
18
+ for_write(str.size + $/.size).puts(str)
19
+ end
20
+
21
+ def write(str)
22
+ for_write(str.size).write(str)
23
+ end
24
+
25
+ def gets
26
+ for_read.gets
27
+ end
28
+
29
+ def read(length = nil, buffer = nil)
30
+ if buffer
31
+ for_read.read(length, buffer)
32
+ else
33
+ for_read.read(length)
34
+ end
35
+ end
36
+
37
+ def each(&block)
38
+ for_read.each(&block)
39
+ end
40
+
41
+ def rewind
42
+ for_read.rewind
43
+ end
44
+
45
+ def close
46
+ for_read.close
47
+ end
48
+
49
+ private
50
+
51
+ def for_read
52
+ @mem || @file
53
+ end
54
+
55
+ def switch_to_file
56
+ mem = @mem
57
+ @mem = nil
58
+ mem.rewind
59
+ @file = make_file(mem.read)
60
+ end
61
+
62
+ def for_write(size)
63
+ if @file
64
+ @file
65
+ elsif (@mem.size + size) <= @limit
66
+ @mem
67
+ else
68
+ switch_to_file
69
+ @file
70
+ end
71
+ end
72
+
73
+ def make_file(data)
74
+ file = Tempfile.new('MemFileBacking')
75
+ file.unlink
76
+ file.write(data)
77
+ file
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,66 @@
1
+ require 'rubylet/rack/tee_io'
2
+ require 'rubylet/rack/mem_file_io'
3
+ require 'stringio'
4
+
5
+ # Wraps an IO with a memory and file backed buffer to support Rack's
6
+ # required #rewind.
7
+ #
8
+ # Only some IO methods are supported.
9
+ module Rubylet::Rack
10
+ class RewindableIO
11
+ def initialize(io, limit = MemFileIO::DEFAULT_LIMIT)
12
+ @buf = MemFileIO.new(limit)
13
+ @io = TeeIO.new(io, @buf)
14
+ end
15
+
16
+ def gets
17
+ str = @buf.gets
18
+ if str.nil? # end of buffer
19
+ @io.gets
20
+ elsif str.end_with?($/) # good, we got a whole line
21
+ str
22
+ else # partial line
23
+ str + (@io.gets || '')
24
+ end
25
+ end
26
+
27
+ def read(length = nil, buffer = nil)
28
+ if length.nil? && buffer.nil?
29
+ @buf.read + @io.read
30
+ elsif length.nil?
31
+ @buf.read(nil, buffer)
32
+ @io.read(nil, buffer)
33
+ elsif buffer.nil?
34
+ str = ''
35
+ @buf.read(length, str)
36
+ if (str.size == length)
37
+ @io.read(length - str.size, str)
38
+ end
39
+ str
40
+ else # both non-nil
41
+ size0 = buffer.size
42
+ @buf.read(length, buffer)
43
+ from_buf = buffer.size - size0
44
+ if (from_buf < length)
45
+ @io.read(length - from_buf, buffer)
46
+ end
47
+ buffer
48
+ end
49
+ end
50
+
51
+ def each
52
+ while s = gets
53
+ yield s
54
+ end
55
+ end
56
+
57
+ def rewind
58
+ @buf.rewind
59
+ end
60
+
61
+ def close
62
+ @buf.close
63
+ @io.close
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,63 @@
1
+ # A Rack compatible session object that forwards to an underlying
2
+ # +javax.servlet.http.HttpSession+.
3
+ module Rubylet; module Rack
4
+ class Session
5
+ # @param [javax.servlet.http.HttpServletRequest] req
6
+ # @param [Hash] options
7
+ # @option options [Integer] :expire_after The max inactive interval, in seconds
8
+ def initialize(req, options={})
9
+ @javaSession = req.getSession
10
+
11
+ if @javaSession.isNew
12
+ if exp = options[:expire_after]
13
+ req.setMaxInactiveInterval exp.to_i
14
+ end
15
+ end
16
+ end
17
+
18
+ def store(key, value)
19
+ @javaSession.setAttribute(key, value)
20
+ end
21
+ alias_method :[]=, :store
22
+
23
+ def fetch(key, default = nil)
24
+ @javaSession.getAttribute(key) || default
25
+ end
26
+ alias_method :[], :fetch
27
+
28
+ def delete(key)
29
+ @javaSession.removeAttribute(key)
30
+ end
31
+
32
+ def clear
33
+ @javaSession.getAttributeNames.each {|key| delete(key) }
34
+ end
35
+
36
+ # This method is not required by the Rack SPEC for session
37
+ # objects, but Rails calls it anyway in +actionpack (3.2.9)
38
+ # lib/action_dispatch/middleware/flash.rb:258:in `call'+
39
+ def has_key?(key)
40
+ !(fetch(key).nil?)
41
+ end
42
+ alias_method :include?, :has_key?
43
+ alias_method :key?, :has_key?
44
+ alias_method :member?, :has_key?
45
+
46
+ # Used by Rails but not required by Rack.
47
+ def destroy
48
+ @javaSession.invalidate
49
+ end
50
+
51
+ def to_hash
52
+ hash = {}
53
+ @javaSession.getAttributeNames.each do
54
+ |key| hash[key] = @javaSession.getAttribute(key)
55
+ end
56
+ hash
57
+ end
58
+
59
+ def inspect
60
+ to_hash.inspect
61
+ end
62
+ end
63
+ end; end
@@ -0,0 +1,29 @@
1
+ require 'rubylet/rack/session'
2
+
3
+ # Rack middleware to make the servlet container's sessions available to ruby.
4
+ module Rubylet
5
+ module Rack
6
+ class Session
7
+ class ContainerStore
8
+ def initialize(app, options={})
9
+ @app = app
10
+ @options = options
11
+ end
12
+
13
+ def call(env)
14
+ context(env)
15
+ end
16
+
17
+ # For Rack::Util::Context
18
+ def context(env, app=@app)
19
+ if req = env['java.servlet_request']
20
+ env['rack.session'] = Session.new(req, @options)
21
+ else
22
+ env['rack.errors'].puts 'java.servlet_request not found; cannot make session'
23
+ end
24
+ app.call(env)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,43 @@
1
+ # All reads on +io+ are copied to +out+. Only supports IO methods
2
+ # specified by Rack Input Stream spec.
3
+ module Rubylet::Rack
4
+ class TeeIO
5
+ def initialize(io, out)
6
+ @io = io
7
+ @out = out
8
+ end
9
+
10
+ # Does not support custom separator per Rack spec
11
+ def gets
12
+ str = @io.gets
13
+ @out.write(str) if str
14
+ str
15
+ end
16
+
17
+ def read(length = nil, buffer = nil)
18
+ str = ''
19
+ ret = @io.read(length, str)
20
+ @out.write(str)
21
+ if buffer
22
+ buffer << str
23
+ if ret.object_id == str.object_id
24
+ buffer
25
+ else
26
+ ret
27
+ end
28
+ else
29
+ ret
30
+ end
31
+ end
32
+
33
+ def each
34
+ while s = gets
35
+ yield s
36
+ end
37
+ end
38
+
39
+ def close
40
+ @io.close
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ require 'rubylet/rack/dechunking_body'
3
+
4
+ module Rubylet::Rack
5
+ describe DechunkingBody do
6
+ def chunk(strs)
7
+ strs.map do |str|
8
+ str.bytesize.to_s(16) + "\r\n" + str + "\r\n"
9
+ end + ["0\r\n\r\n"]
10
+ end
11
+
12
+ def dechunk(body)
13
+ ''.tap do |str|
14
+ DechunkingBody.new(body).each { |part| str << part }
15
+ end
16
+ end
17
+
18
+ it 'de-chunks a chunked body' do
19
+ data = ["some", "data", "\n in chunks."]
20
+ expected = data.join
21
+ assert_equal expected, dechunk(chunk(data))
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+ require 'rubylet/rack/mem_file_io'
3
+
4
+ module Rubylet::Rack
5
+
6
+ describe MemFileIO do
7
+
8
+ it 'writes data with puts' do
9
+ @io = MemFileIO.new
10
+ @io.puts('hello')
11
+ @io.rewind
12
+ @io.read.must_equal "hello#{$/}"
13
+ end
14
+
15
+ it 'writes data with write' do
16
+ @io = MemFileIO.new
17
+ @io.write('hello')
18
+ @io.rewind
19
+ @io.read.must_equal 'hello'
20
+ end
21
+
22
+ it 'allows multiple rewind' do
23
+ @io = MemFileIO.new
24
+
25
+ @io.write('hello')
26
+ @io.rewind
27
+ @io.read.must_equal 'hello'
28
+
29
+ @io.write('hello')
30
+ @io.rewind
31
+ @io.read.must_equal 'hellohello'
32
+ end
33
+
34
+ it 'overwrites? (FIXME: is this correct?)' do
35
+ @io = MemFileIO.new
36
+
37
+ @io.write('hello')
38
+ @io.rewind
39
+ @io.read.must_equal 'hello'
40
+
41
+ @io.rewind
42
+ @io.write('***')
43
+ @io.rewind
44
+ @io.read.must_equal '***lo'
45
+ end
46
+
47
+ it 'switches to backing file' do
48
+ @io = MemFileIO.new(4)
49
+ @io.write('1234')
50
+ @io.write('5678')
51
+ @io.rewind
52
+ @io.read.must_equal '12345678'
53
+ end
54
+
55
+ it 'returns nil on EOF' do
56
+ @io = MemFileIO.new
57
+ @io.read
58
+ @io.read(1).must_equal nil
59
+ end
60
+
61
+ it 'returns empty string on EOF' do
62
+ @io = MemFileIO.new
63
+ @io.read
64
+ @io.read.must_equal ''
65
+ end
66
+ end
67
+
68
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+ require 'rubylet/rack/rewindable_io'
3
+ require 'stringio'
4
+
5
+ module Rubylet::Rack
6
+
7
+ describe RewindableIO do
8
+
9
+ data = "some data\nwith newlines\nanother line"
10
+
11
+ before :each do
12
+ @io = StringIO.new
13
+ @io.write(data)
14
+ @io.rewind
15
+
16
+ @reio = RewindableIO.new(@io)
17
+ end
18
+
19
+ it 'rewinds' do
20
+ @reio.read.must_equal data
21
+ @reio.rewind
22
+ @reio.read.must_equal data
23
+ end
24
+
25
+ it 'rewinds with file spill over' do
26
+ expected = ''
27
+ 10.times do
28
+ @io.write(data)
29
+ expected << data
30
+ end
31
+ @io.rewind
32
+
33
+ @reio = RewindableIO.new(@io, 32)
34
+ @reio.read.must_equal expected
35
+ @reio.rewind
36
+ @reio.read.must_equal expected
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+ require 'rubylet/rack/tee_io'
3
+ require 'stringio'
4
+
5
+ module Rubylet::Rack
6
+
7
+ describe TeeIO do
8
+
9
+ DATA = "some data\nwith newlines\nanother line"
10
+
11
+ before :each do
12
+ @io = StringIO.new
13
+ @io.write(DATA)
14
+ @io.rewind
15
+
16
+ @out = StringIO.new
17
+
18
+ @tee = TeeIO.new(@io, @out)
19
+ end
20
+
21
+ it 'copies data on read' do
22
+ @tee.read
23
+ @out.rewind
24
+ @out.read.must_equal DATA
25
+ end
26
+
27
+ describe '#gets' do
28
+ it 'copies data on gets' do
29
+ @tee.gets
30
+ @out.rewind
31
+ @out.read.must_equal "some data\n"
32
+ end
33
+
34
+ it 'returns nil on EOF' do
35
+ @tee.read
36
+ @tee.gets.must_equal nil
37
+ end
38
+ end
39
+
40
+ it 'copies data on each' do
41
+ @tee.each {}
42
+ @out.rewind
43
+ @out.read.must_equal DATA
44
+ end
45
+
46
+ it 'copies data byte by byte' do
47
+ @tee.read(1)
48
+ @tee.read(1)
49
+ @out.rewind
50
+ @out.read.must_equal 'so'
51
+ end
52
+
53
+ it 'reads data into a given buffer' do
54
+ buf = String.new
55
+ ret = @tee.read nil, buf
56
+
57
+ ret.object_id.must_equal buf.object_id
58
+
59
+ buf.must_equal DATA
60
+ @out.rewind
61
+ @out.read.must_equal DATA
62
+ end
63
+
64
+ it 'returns nil on EOF' do
65
+ @tee.read
66
+ @tee.read(1).must_equal nil
67
+ end
68
+
69
+ it 'returns empty string on EOF' do
70
+ @tee.read
71
+ @tee.read.must_equal ''
72
+ end
73
+ end
74
+
75
+ end
@@ -0,0 +1,5 @@
1
+ require 'minitest/spec'
2
+ require 'minitest/autorun'
3
+ require 'minitest/matchers'
4
+
5
+ module Rubylet; module Rack; end; end;
metadata ADDED
@@ -0,0 +1,191 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubylet-rack
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: 6
5
+ version: 2.0.0.pre1
6
+ platform: java
7
+ authors:
8
+ - Patrick Mahoney
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-03-28 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rack
16
+ version_requirements: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: !binary |-
21
+ MA==
22
+ none: false
23
+ requirement: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: !binary |-
28
+ MA==
29
+ none: false
30
+ prerelease: false
31
+ type: :runtime
32
+ - !ruby/object:Gem::Dependency
33
+ name: mechanize
34
+ version_requirements: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: !binary |-
39
+ MA==
40
+ none: false
41
+ requirement: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: !binary |-
46
+ MA==
47
+ none: false
48
+ prerelease: false
49
+ type: :development
50
+ - !ruby/object:Gem::Dependency
51
+ name: mini_aether
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: !binary |-
57
+ MA==
58
+ none: false
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: !binary |-
64
+ MA==
65
+ none: false
66
+ prerelease: false
67
+ type: :development
68
+ - !ruby/object:Gem::Dependency
69
+ name: minitest-matchers
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: !binary |-
75
+ MA==
76
+ none: false
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: !binary |-
82
+ MA==
83
+ none: false
84
+ prerelease: false
85
+ type: :development
86
+ - !ruby/object:Gem::Dependency
87
+ name: rake
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: !binary |-
93
+ MA==
94
+ none: false
95
+ requirement: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: !binary |-
100
+ MA==
101
+ none: false
102
+ prerelease: false
103
+ type: :development
104
+ - !ruby/object:Gem::Dependency
105
+ name: unf
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "<="
109
+ - !ruby/object:Gem::Version
110
+ version: 0.0.5
111
+ none: false
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "<="
115
+ - !ruby/object:Gem::Version
116
+ version: 0.0.5
117
+ none: false
118
+ prerelease: false
119
+ type: :development
120
+ - !ruby/object:Gem::Dependency
121
+ name: version
122
+ version_requirements: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - "~>"
125
+ - !ruby/object:Gem::Version
126
+ version: !binary |-
127
+ MQ==
128
+ none: false
129
+ requirement: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - "~>"
132
+ - !ruby/object:Gem::Version
133
+ version: !binary |-
134
+ MQ==
135
+ none: false
136
+ prerelease: false
137
+ type: :development
138
+ description: Java Servlet implementation that forwards to Rack application
139
+ email:
140
+ - pat@polycrystal.org
141
+ executables: []
142
+ extensions: []
143
+ extra_rdoc_files: []
144
+ files:
145
+ - VERSION
146
+ - MIT-LICENSE
147
+ - lib/rubylet/rack/ext.jar
148
+ - lib/rubylet/rack.rb
149
+ - lib/rubylet/rack/dechunking_body.rb
150
+ - lib/rubylet/rack/errors.rb
151
+ - lib/rubylet/rack/logger.rb
152
+ - lib/rubylet/rack/mem_file_io.rb
153
+ - lib/rubylet/rack/rewindable_io.rb
154
+ - lib/rubylet/rack/session.rb
155
+ - lib/rubylet/rack/tee_io.rb
156
+ - lib/rubylet/rack/session/container_store.rb
157
+ - spec/spec_helper.rb
158
+ - spec/rubylet/rack/dechunking_body_spec.rb
159
+ - spec/rubylet/rack/mem_file_io_spec.rb
160
+ - spec/rubylet/rack/rewindable_io_spec.rb
161
+ - spec/rubylet/rack/tee_io_spec.rb
162
+ homepage:
163
+ licenses: []
164
+ post_install_message:
165
+ rdoc_options: []
166
+ require_paths:
167
+ - lib
168
+ required_ruby_version: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ segments:
173
+ - 0
174
+ hash: 2
175
+ version: !binary |-
176
+ MA==
177
+ none: false
178
+ required_rubygems_version: !ruby/object:Gem::Requirement
179
+ requirements:
180
+ - - !binary |-
181
+ Pg==
182
+ - !ruby/object:Gem::Version
183
+ version: 1.3.1
184
+ none: false
185
+ requirements: []
186
+ rubyforge_project:
187
+ rubygems_version: 1.8.24
188
+ signing_key:
189
+ specification_version: 3
190
+ summary: Java Servlet implementation that forwards to Rack application
191
+ test_files: []