hessian2 1.1.1 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -2
  3. data/LICENSE.txt +22 -0
  4. data/README.md +161 -0
  5. data/hessian2.gemspec +3 -2
  6. data/lib/hessian2.rb +12 -4
  7. data/lib/hessian2/class_wrapper.rb +89 -0
  8. data/lib/hessian2/client.rb +38 -0
  9. data/lib/hessian2/constants.rb +164 -0
  10. data/lib/hessian2/em_client.rb +52 -0
  11. data/lib/hessian2/fault.rb +3 -0
  12. data/lib/hessian2/handler.rb +15 -0
  13. data/lib/hessian2/hessian_client.rb +3 -38
  14. data/lib/hessian2/parser.rb +619 -0
  15. data/lib/hessian2/struct_wrapper.rb +55 -0
  16. data/lib/hessian2/type_wrapper.rb +49 -8
  17. data/lib/hessian2/version.rb +1 -1
  18. data/lib/hessian2/writer.rb +498 -0
  19. data/spec/binary_spec.rb +51 -0
  20. data/spec/boolean_spec.rb +26 -0
  21. data/spec/class_wrapper_spec.rb +52 -0
  22. data/spec/create_monkeys.rb +14 -0
  23. data/spec/date_spec.rb +45 -0
  24. data/spec/double_spec.rb +78 -0
  25. data/spec/int_spec.rb +54 -0
  26. data/spec/list_spec.rb +66 -0
  27. data/spec/long_spec.rb +68 -0
  28. data/spec/map_spec.rb +36 -0
  29. data/spec/null_spec.rb +17 -0
  30. data/spec/object_spec.rb +65 -0
  31. data/spec/ref_spec.rb +43 -0
  32. data/spec/spec_helper.rb +23 -0
  33. data/spec/string_spec.rb +61 -0
  34. data/spec/struct_wrapper_spec.rb +47 -0
  35. data/spec/type_wrapper_spec.rb +102 -0
  36. data/test/app.rb +15 -0
  37. data/test/client.rb +9 -0
  38. data/test/config.ru +2 -0
  39. data/test/monkey_service.rb +12 -0
  40. metadata +79 -19
  41. data/README.rdoc +0 -21
  42. data/lib/hessian2/hessian_exception.rb +0 -3
  43. data/lib/hessian2/hessian_parser.rb +0 -75
  44. data/lib/hessian2/hessian_writer.rb +0 -130
  45. data/test/test_hessian_parser.rb +0 -56
data/spec/map_spec.rb ADDED
@@ -0,0 +1,36 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ module Hessian2
4
+ describe Writer do
5
+ context "when map" do
6
+ hash = { born_at: Time.new(2009, 5, 8), name: '大鸡', price: 99.99 }
7
+
8
+ it "should write map with type ('M') ::= M type (value value)* Z" do
9
+ type = 'Monkey'
10
+ bin = Hessian2.write(Hessian2::TypeWrapper.new(type, hash))
11
+
12
+ bytes = bin.each_byte
13
+ expect([ bytes.next ].pack('C')).to eq('M')
14
+ expect(Hessian2.parse_string(bytes)).to eq(type)
15
+ _hash = Hessian2.parse(bin)
16
+ expect([ _hash['born_at'], _hash['name'], _hash['price'] ]).to eq([ hash[:born_at], hash[:name], hash[:price] ])
17
+ _hash2 = Hessian2.parse(bin, nil, symbolize_keys: true)
18
+ expect(_hash2).to eq(hash)
19
+ end
20
+
21
+
22
+ it "should write untyped map ::= 'H' (value value)* 'Z'" do
23
+ bin = Hessian2.write(hash)
24
+
25
+ bytes = bin.each_byte
26
+ expect(bin[0]).to eq('H')
27
+ expect(bin[-1]).to eq('Z')
28
+ _hash = Hessian2.parse(bin)
29
+ expect([ _hash['born_at'], _hash['name'], _hash['price'] ]).to eq([ hash[:born_at], hash[:name], hash[:price] ])
30
+ _hash2 = Hessian2.parse(bin, nil, symbolize_keys: true)
31
+ expect(_hash2).to eq(hash)
32
+ end
33
+
34
+ end
35
+ end
36
+ end
data/spec/null_spec.rb ADDED
@@ -0,0 +1,17 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ module Hessian2
4
+ describe Writer do
5
+ context "when null" do
6
+
7
+ it "should write null ('N') ::= 'N'" do
8
+ val = nil
9
+ bin = Hessian2.write(val)
10
+
11
+ expect(bin).to eq('N')
12
+ expect(Hessian2.parse(bin)).to eq(val)
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,65 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ module Hessian2
4
+ describe Writer do
5
+ context "when object" do
6
+ hash = { id: nil, born_at: Time.new(2009, 5, 8), name: '大鸡', price: 99.99 }
7
+
8
+ it "should write object type definition ('C') ::= 'C' string int string* and object with direct type ::= [x60-x6f] value*" do
9
+ [ 'Monkey', 'AnotherMonkey' ].each do |klass|
10
+ bin = Hessian2.write(Kernel.const_get(klass).new(hash))
11
+
12
+ bytes = bin.each_byte
13
+ expect([ bytes.next ].pack('C')).to eq('C')
14
+ expect(Hessian2.parse_string(bytes)).to eq(klass)
15
+ expect(Hessian2.parse_int(bytes)).to eq(4)
16
+ 4.times{ Hessian2.parse_string(bytes) }
17
+ expect(bytes.next - 0x60).to eq(0)
18
+ _monkey = Hessian2.parse(bin)
19
+ expect([ _monkey.born_at, _monkey.name, _monkey.price ]).to eq([ hash[:born_at], hash[:name], hash[:price] ])
20
+ end
21
+ end
22
+
23
+
24
+ it "should write object instance ('O') ::= 'O' int value*" do
25
+ arr = []
26
+ 17.times do |i|
27
+ arr << Hessian2::ClassWrapper.new("com.sun.java.Monkey#{i}", hash)
28
+ end
29
+ bin = Hessian2.write(arr)
30
+
31
+ bytes = bin.each_byte
32
+
33
+ # skip x58 int
34
+ bytes.next
35
+ Hessian2.parse_int(bytes)
36
+
37
+ # skip top 16
38
+ 16.times do
39
+ bytes.next
40
+ Hessian2.parse_string(bytes)
41
+ Hessian2.parse_int(bytes)
42
+ 4.times{ Hessian2.parse_string(bytes) }
43
+ bytes.next
44
+ 4.times{ Hessian2.parse_bytes(bytes) }
45
+ end
46
+
47
+ # skip 17th class definition
48
+ bytes.next
49
+ Hessian2.parse_string(bytes)
50
+ Hessian2.parse_int(bytes)
51
+ 4.times{ Hessian2.parse_string(bytes) }
52
+
53
+ expect([ bytes.next ].pack('C')).to eq('O')
54
+ expect(Hessian2.parse_int(bytes)).to eq(16)
55
+
56
+ _monkeys = Hessian2.parse(bin)
57
+ expect(_monkeys.size).to eq(17)
58
+ _monkeys.each do |_monkey|
59
+ expect([ _monkey.born_at, _monkey.name, _monkey.price ]).to eq([ hash[:born_at], hash[:name], hash[:price] ])
60
+ end
61
+ end
62
+
63
+ end
64
+ end
65
+ end
data/spec/ref_spec.rb ADDED
@@ -0,0 +1,43 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ module Hessian2
4
+ describe Writer do
5
+ context "when ref" do
6
+ hash1 = { id: nil, born_at: Time.new(2009, 5, 8), name: '大鸡', price: 99.99 }
7
+
8
+ it "should write reference to map/list/object - integer ('Q') ::= x51 int" do
9
+ monkey1 = Monkey.new(hash1)
10
+ monkey2 = Hessian2::ClassWrapper.new("com.sun.java.Monkey", hash1)
11
+ monkey3 = Hessian2::TypeWrapper.new("com.sun.java.Monkey", hash1)
12
+ monkeys1 = [ monkey1, monkey2, monkey3 ]
13
+ monkeys2 = Hessian2::ClassWrapper.new("[com.sun.java.Monkey", monkeys1)
14
+ monkeys3 = Hessian2::TypeWrapper.new("[com.sun.java.Monkey", monkeys1)
15
+
16
+ arr = [ hash1, monkey1, monkey2, monkey3, monkeys1, monkeys2, monkeys3 ] * 2
17
+
18
+ bin = Hessian2.write(arr)
19
+
20
+ _hash1, _monkey1, _monkey2, _monkey3, _monkeys1, _monkeys2, _monkeys3, \
21
+ _hash1r, _monkey1r, _monkey2r, _monkey3r, _monkeys1r, _monkeys2r, _monkeys3r = Hessian2.parse(bin, nil, symbolize_keys: true)
22
+
23
+ [ _hash1, _hash1r, _monkey3, _monkey3r ].each do |_hash|
24
+ expect([ _hash[:born_at], _hash[:name], _hash[:price] ]).to eq([ hash1[:born_at], hash1[:name], hash1[:price] ])
25
+ end
26
+
27
+ [ _monkey1, _monkey2, _monkey1r, _monkey2r ].each do |_monkey|
28
+ expect([ _monkey.born_at, _monkey.name, _monkey.price ]).to eq([ hash1[:born_at], hash1[:name], hash1[:price] ])
29
+ end
30
+
31
+ [ _monkeys1, _monkeys2, _monkeys3, _monkeys1r, _monkeys2r, _monkeys3r ].each do |_monkeys|
32
+ [ _monkeys[0], _monkeys[1] ].each do |_monkey|
33
+ expect([ _monkey.born_at, _monkey.name, _monkey.price ]).to eq([ hash1[:born_at], hash1[:name], hash1[:price] ])
34
+ end
35
+ last = _monkeys.last
36
+ expect([ last[:born_at], last[:name], last[:price] ]).to eq([ hash1[:born_at], hash1[:name], hash1[:price] ])
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,23 @@
1
+ lib_path = File.expand_path('../../lib', __FILE__)
2
+ $:.unshift(lib_path)
3
+
4
+ require 'hessian2'
5
+
6
+ require 'active_record'
7
+ require 'mysql2'
8
+
9
+ MonkeyStruct = Struct.new(:born_at, :id, :name, :price)
10
+
11
+ options = YAML.load_file(File.expand_path('../database.yml', __FILE__))
12
+ ActiveRecord::Base.establish_connection(options)
13
+ ActiveRecord::Base.default_timezone = :local
14
+
15
+ class Monkey < ActiveRecord::Base; end
16
+
17
+ class AnotherMonkey
18
+ attr_accessor :born_at, :id, :name, :price
19
+
20
+ def initialize(attrs = {})
21
+ attrs.each { |k, v| send("#{k}=", v) if respond_to?("#{k}=") }
22
+ end
23
+ end
@@ -0,0 +1,61 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ module Hessian2
4
+ describe Writer do
5
+ context "when string" do
6
+
7
+ it "should write utf-8 string length 0-31 ::= [x00-x1f] <utf8-data>" do
8
+ (0..31).each do |len|
9
+ val = '啦' * len
10
+ bin = Hessian2.write(val)
11
+
12
+ expect(bin[0].unpack('C').first).to eq(val.size)
13
+ expect(bin[1..-1]).to eq(val.b)
14
+ expect(Hessian2.parse(bin)).to eq(val)
15
+ end
16
+ end
17
+
18
+
19
+ it "should write utf-8 string length 0-1023 ::= [x30-x33] b0 <utf8-data>" do
20
+ [ 33, 256, 512, 1023 ].each do |len|
21
+ val = '啦' * len
22
+ bin = Hessian2.write(val)
23
+
24
+ b1, b0 = bin[0, 2].unpack('CC')
25
+ expect(256 * (b1 - 0x30) + b0).to eq(val.size)
26
+ expect(bin[2..-1]).to eq(val.b)
27
+ expect(Hessian2.parse(bin)).to eq(val)
28
+ end
29
+ end
30
+
31
+ it "should write utf-8 string final chunk ('S') ::= S b1 b0 <utf8-data>" do
32
+ val = '啦' * 0x400
33
+ bin = Hessian2.write(val)
34
+
35
+ expect(bin[0]).to eq('S')
36
+ expect(bin[1, 2].unpack('n').first).to eq(0x400)
37
+ expect(Hessian2.parse(bin)).to eq(val)
38
+ end
39
+
40
+
41
+ it "should write utf-8 string non-final chunk ('R') ::= x52 b1 b0 <utf8-data>" do
42
+ val = '啦' * 0x10400
43
+ bin = Hessian2.write(val)
44
+
45
+ chunks = val.size / 0x8000
46
+ i = 0
47
+
48
+ chunks.times do |c|
49
+ expect(bin[i]).to eq('R')
50
+ expect(bin[i + 1, 2].unpack('n').first).to eq(0x8000)
51
+ i += (3 + val[c * 0x8000, 0x8000].bytesize)
52
+ end
53
+
54
+ expect(bin[i]).to eq('S')
55
+ expect(bin[i + 1, 2].unpack('n').first).to eq(val.size - 0x8000 * chunks)
56
+ expect(Hessian2.parse(bin)).to eq(val)
57
+ end
58
+
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,47 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ module Hessian2
4
+ describe StructWrapper do
5
+ hash = { id: nil, born_at: Time.new(2009, 5, 8), name: '大鸡', price: 99.99 }
6
+
7
+ # it "should raise error" do
8
+ # expect(lambda{ Hessian2::StructWrapper.new(MonkeyStruct) }).to raise_error
9
+ # end
10
+
11
+
12
+ # it "should wrap nil" do
13
+ # bin = Hessian2.write(Hessian2::StructWrapper.new(MonkeyStruct, nil))
14
+
15
+ # _monkey = Hessian2.parse(bin, MonkeyStruct)
16
+ # expect(_monkey).to eq(nil)
17
+ # end
18
+
19
+
20
+ # it "should wrap hash, monkey, another monkey" do
21
+ # [ MonkeyStruct, 'MonkeyStruct' ].each do |klass|
22
+ # [ hash, Monkey.new(hash), AnotherMonkey.new(hash) ].each do |val|
23
+ # bin = Hessian2.write(Hessian2::StructWrapper.new(klass, val))
24
+
25
+ # _monkey = Hessian2.parse(bin, klass)
26
+ # expect([ _monkey.born_at, _monkey.name, _monkey.price ]).to eq([ hash[:born_at], hash[:name], hash[:price] ])
27
+ # end
28
+ # end
29
+ # end
30
+
31
+
32
+ it "should wrap array" do
33
+ [ [MonkeyStruct], '[MonkeyStruct' ].each do |klass|
34
+ arr = [ nil, hash, Monkey.new(hash), AnotherMonkey.new(hash) ]
35
+ bin = Hessian2.write(Hessian2::StructWrapper.new(klass, arr))
36
+
37
+ _monkey1, _monkey2, _monkey3, _monkey4 = Hessian2.parse(bin, klass, symbolize_keys: true)
38
+ expect(_monkey1).to eq(nil)
39
+ expect([ _monkey2[:born_at], _monkey2[:name], _monkey2[:price] ]).to eq([ hash[:born_at], hash[:name], hash[:price] ])
40
+ [ _monkey3, _monkey4 ].each do |_monkey|
41
+ expect([ _monkey.born_at, _monkey.name, _monkey.price ]).to eq([ hash[:born_at], hash[:name], hash[:price] ])
42
+ end
43
+ end
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,102 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ module Hessian2
4
+ describe TypeWrapper do
5
+ hash = { id: nil, born_at: Time.new(2009, 5, 8), name: '大鸡', price: 99.99 }
6
+
7
+ it "should raise error" do
8
+ expect(lambda{ Hessian2::TypeWrapper.new(:unknown) }).to raise_error
9
+ end
10
+
11
+
12
+ it "should wrap nil" do
13
+ bin = Hessian2.write(Hessian2::TypeWrapper.new(:unknown, nil))
14
+
15
+ expect(bin).to eq('N')
16
+ expect(Hessian2.parse(bin)).to eq(nil)
17
+ end
18
+
19
+
20
+ it "should wrap long" do
21
+ [ 59, '59' ].each do |val|
22
+ [ 'L', 'l', 'Long', 'long', :long ].each do |type|
23
+ bin = Hessian2.write(Hessian2::TypeWrapper.new(type, val))
24
+
25
+ b1, b0 = bin[0, 2].unpack('CC')
26
+ expect(((b1 - 0xf8) << 8) + b0).to eq(Integer(val))
27
+ expect(Hessian2.parse(bin)).to eq(Integer(val))
28
+ end
29
+ end
30
+ end
31
+
32
+
33
+ it "should wrap int" do
34
+ [ 0x7f_fff_fff, '0x7f_fff_fff' ].each do |val|
35
+ [ 'I', 'i', 'Integer', 'int', :int ].each do |type|
36
+ bin = Hessian2.write(Hessian2::TypeWrapper.new(type, val))
37
+
38
+ expect(bin[0]).to eq('I')
39
+ expect(bin[1, 4].unpack('l>').first).to eq(Integer(val))
40
+ expect(Hessian2.parse(bin)).to eq(Integer(val))
41
+ end
42
+ end
43
+ end
44
+
45
+
46
+ it "should wrap binary" do
47
+ val = 'b' * 59
48
+ [ 'B', 'b', 'Binary', 'bin', :bin ].each do |type|
49
+ bin = Hessian2.write(Hessian2::TypeWrapper.new(type, val))
50
+
51
+ b1, b0 = bin[0, 2].unpack('CC')
52
+ expect(256 * (b1 - 0x34) + b0).to eq(val.size)
53
+ expect(bin.size).to eq(2 + val.size)
54
+ expect(Hessian2.parse(bin)).to eq(val)
55
+ end
56
+ end
57
+
58
+
59
+ it "should wrap monkey" do
60
+ [ Monkey.new(hash), AnotherMonkey.new(hash) ].each do |val|
61
+ bin = Hessian2.write(Hessian2::TypeWrapper.new('com.sun.java.Monkey', val))
62
+
63
+ _hash = Hessian2.parse(bin, nil, symbolize_keys: true)
64
+ expect([ _hash[:born_at], _hash[:name], _hash[:price] ]).to eq([ hash[:born_at], hash[:name], hash[:price] ])
65
+ end
66
+ end
67
+
68
+
69
+ it "should wrap long array" do
70
+ bin = Hessian2.write(Hessian2::TypeWrapper.new('[long', [ 59, 69, 79, 89, 99 ]))
71
+
72
+ expect(Hessian2.parse(bin)).to eq([ 59, 69, 79, 89, 99 ])
73
+ end
74
+
75
+
76
+ it "should wrap int array" do
77
+ bin = Hessian2.write(Hessian2::TypeWrapper.new('[int', [ 0x7f_fff_ffb, 0x7f_fff_ffc, 0x7f_fff_ffd, 0x7f_fff_ffe, 0x7f_fff_fff ]))
78
+
79
+ expect(Hessian2.parse(bin)).to eq([ 0x7f_fff_ffb, 0x7f_fff_ffc, 0x7f_fff_ffd, 0x7f_fff_ffe, 0x7f_fff_fff ])
80
+ end
81
+
82
+
83
+ it "should wrap binary array" do
84
+ bin = Hessian2.write(Hessian2::TypeWrapper.new('[bin', [ 'b' * 59, 'b' * 69, 'b' * 79, 'b' * 89, 'b' * 99 ]))
85
+
86
+ expect(Hessian2.parse(bin)).to eq([ 'b' * 59, 'b' * 69, 'b' * 79, 'b' * 89, 'b' * 99 ])
87
+ end
88
+
89
+
90
+ it "should wrap monkey array" do
91
+ bin = Hessian2.write(Hessian2::TypeWrapper.new('[com.sun.java.Monkey', [ nil, Monkey.new(hash), AnotherMonkey.new(hash) ]))
92
+
93
+ _hash1, _hash2, _hash3 = Hessian2.parse(bin, nil, symbolize_keys: true)
94
+ expect(_hash1).to eq(nil)
95
+ [ _hash2, _hash3 ].each do |_hash|
96
+ expect([ _hash[:born_at], _hash[:name], _hash[:price] ]).to eq([ hash[:born_at], hash[:name], hash[:price] ])
97
+ end
98
+ end
99
+
100
+
101
+ end
102
+ end
data/test/app.rb ADDED
@@ -0,0 +1,15 @@
1
+ lib_path = File.expand_path('../../lib', __FILE__)
2
+ $:.unshift(lib_path)
3
+ require 'sinatra'
4
+ require File.expand_path('../monkey_service', __FILE__)
5
+
6
+ set :logging, false
7
+
8
+ get '/' do
9
+ status 405
10
+ 'post me'
11
+ end
12
+
13
+ post '/' do
14
+ MonkeyService.handle(request.body.read)
15
+ end
data/test/client.rb ADDED
@@ -0,0 +1,9 @@
1
+ lib_path = File.expand_path('../../lib', __FILE__)
2
+ $:.unshift(lib_path)
3
+ require 'hessian2'
4
+
5
+ client = Hessian2::Client.new('http://localhost:4567')
6
+
7
+ puts client.say ARGV.first
8
+
9
+ puts client.say2
data/test/config.ru ADDED
@@ -0,0 +1,2 @@
1
+ require ::File.expand_path('../app', __FILE__)
2
+ run Sinatra::Application
@@ -0,0 +1,12 @@
1
+ lib_path = File.expand_path('../../lib', __FILE__)
2
+ $:.unshift(lib_path)
3
+ require 'hessian2'
4
+
5
+ class MonkeyService
6
+ extend Hessian2::Handler
7
+
8
+ def self.say(name)
9
+ "hello #{name}"
10
+ end
11
+
12
+ end