mkrf 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (186) hide show
  1. data/CHANGELOG +2 -0
  2. data/MIT-LICENSE +7 -0
  3. data/README +54 -0
  4. data/Rakefile +107 -0
  5. data/lib/mkrf.rb +4 -0
  6. data/lib/mkrf/availability.rb +219 -0
  7. data/lib/mkrf/generator.rb +146 -0
  8. data/test/abstract_unit.rb +4 -0
  9. data/test/fixtures/down_a_directory/header_down_a_directory.h +1 -0
  10. data/test/fixtures/stdmkrf.h +1 -0
  11. data/test/sample_files/libtrivial/Rakefile +31 -0
  12. data/test/sample_files/libtrivial/extconf.rb +3 -0
  13. data/test/sample_files/libtrivial/lib/libtrivial.c +5 -0
  14. data/test/sample_files/libtrivial/lib/libtrivial.o +0 -0
  15. data/test/sample_files/libtrivial/libtrivial_so.bundle +0 -0
  16. data/test/sample_files/libtrivial/mkrf.log +1 -0
  17. data/test/sample_files/libxml-ruby-0.3.8/CHANGELOG +74 -0
  18. data/test/sample_files/libxml-ruby-0.3.8/LICENSE +22 -0
  19. data/test/sample_files/libxml-ruby-0.3.8/README +144 -0
  20. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/cbg.c +76 -0
  21. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/extconf.rb +49 -0
  22. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/libxml.c +86 -0
  23. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/libxml.h +82 -0
  24. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/libxml.rb +107 -0
  25. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/mkrf.log +1 -0
  26. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/old_extconf.rb +95 -0
  27. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_attr.c +372 -0
  28. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_attr.h +21 -0
  29. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_attribute.c +224 -0
  30. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_attribute.h +21 -0
  31. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_document.c +1159 -0
  32. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_document.h +27 -0
  33. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_dtd.c +168 -0
  34. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_dtd.h +17 -0
  35. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_input_cbg.c +167 -0
  36. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_input_cbg.h +21 -0
  37. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_node.c +2139 -0
  38. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_node.h +28 -0
  39. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_node_set.c +248 -0
  40. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_node_set.h +26 -0
  41. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_ns.c +153 -0
  42. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_ns.h +21 -0
  43. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_parser.c +1417 -0
  44. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_parser.h +31 -0
  45. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_parser_context.c +715 -0
  46. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_parser_context.h +22 -0
  47. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_sax_parser.c +426 -0
  48. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_sax_parser.h +52 -0
  49. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_schema.c +142 -0
  50. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_schema.h +16 -0
  51. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_tree.c +43 -0
  52. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_tree.h +12 -0
  53. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_xinclude.c +20 -0
  54. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_xinclude.h +13 -0
  55. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_xpath.c +363 -0
  56. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_xpath.h +24 -0
  57. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_xpath_context.c +125 -0
  58. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_xpath_context.h +24 -0
  59. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_xpointer.c +100 -0
  60. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_xpointer.h +27 -0
  61. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_xpointer_context.c +21 -0
  62. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_xpointer_context.h +18 -0
  63. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/sax_parser_callbacks.inc +202 -0
  64. data/test/sample_files/syck-0.55/CHANGELOG +186 -0
  65. data/test/sample_files/syck-0.55/COPYING +54 -0
  66. data/test/sample_files/syck-0.55/Makefile +582 -0
  67. data/test/sample_files/syck-0.55/Makefile.am +5 -0
  68. data/test/sample_files/syck-0.55/Makefile.in +582 -0
  69. data/test/sample_files/syck-0.55/README +105 -0
  70. data/test/sample_files/syck-0.55/README.BYTECODE +484 -0
  71. data/test/sample_files/syck-0.55/README.EXT +444 -0
  72. data/test/sample_files/syck-0.55/RELEASE +123 -0
  73. data/test/sample_files/syck-0.55/TODO +25 -0
  74. data/test/sample_files/syck-0.55/aclocal.m4 +883 -0
  75. data/test/sample_files/syck-0.55/bootstrap +7 -0
  76. data/test/sample_files/syck-0.55/config.h +79 -0
  77. data/test/sample_files/syck-0.55/config.h.in +78 -0
  78. data/test/sample_files/syck-0.55/config.status +1197 -0
  79. data/test/sample_files/syck-0.55/config/README +14 -0
  80. data/test/sample_files/syck-0.55/config/depcomp +529 -0
  81. data/test/sample_files/syck-0.55/config/install-sh +323 -0
  82. data/test/sample_files/syck-0.55/config/missing +357 -0
  83. data/test/sample_files/syck-0.55/configure +6728 -0
  84. data/test/sample_files/syck-0.55/configure.in +36 -0
  85. data/test/sample_files/syck-0.55/ext/ruby/CHANGELOG +303 -0
  86. data/test/sample_files/syck-0.55/ext/ruby/README +400 -0
  87. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/MANIFEST +1 -0
  88. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/bytecode.c +1170 -0
  89. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/emitter.c +1224 -0
  90. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/extconf.rb +10 -0
  91. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/gram.c +1894 -0
  92. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/gram.h +79 -0
  93. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/handler.c +174 -0
  94. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/implicit.c +2989 -0
  95. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/mkrf.log +1 -0
  96. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/node.c +407 -0
  97. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/rubyext.c +2385 -0
  98. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/syck.c +504 -0
  99. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/syck.h +458 -0
  100. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/token.c +2707 -0
  101. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/yaml2byte.c +250 -0
  102. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/yamlbyte.h +170 -0
  103. data/test/sample_files/syck-0.55/ext/ruby/install.rb +1022 -0
  104. data/test/sample_files/syck-0.55/ext/ruby/lib/okay.rb +161 -0
  105. data/test/sample_files/syck-0.55/ext/ruby/lib/okay/news.rb +69 -0
  106. data/test/sample_files/syck-0.55/ext/ruby/lib/okay/rpc.rb +434 -0
  107. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml.rb +436 -0
  108. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/baseemitter.rb +247 -0
  109. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/basenode.rb +216 -0
  110. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/compat.rb +26 -0
  111. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/constants.rb +45 -0
  112. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/dbm.rb +111 -0
  113. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/emitter.rb +107 -0
  114. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/encoding.rb +33 -0
  115. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/error.rb +34 -0
  116. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/rubytypes.rb +438 -0
  117. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/store.rb +29 -0
  118. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/stream.rb +40 -0
  119. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/stringio.rb +83 -0
  120. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/syck.rb +19 -0
  121. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/tag.rb +86 -0
  122. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/types.rb +188 -0
  123. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/yamlnode.rb +54 -0
  124. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/ypath.rb +52 -0
  125. data/test/sample_files/syck-0.55/ext/ruby/lib/yod.rb +1168 -0
  126. data/test/sample_files/syck-0.55/ext/ruby/samples/okayNews-modules.rb +27 -0
  127. data/test/sample_files/syck-0.55/ext/ruby/samples/okayNews-sample.rb +336 -0
  128. data/test/sample_files/syck-0.55/ext/ruby/samples/okayNews-validate.rb +341 -0
  129. data/test/sample_files/syck-0.55/ext/ruby/samples/okayRpc-client.rb +51 -0
  130. data/test/sample_files/syck-0.55/ext/ruby/samples/okayRpc-server.rb +85 -0
  131. data/test/sample_files/syck-0.55/ext/ruby/samples/yaml-sortHashKeys.rb +128 -0
  132. data/test/sample_files/syck-0.55/ext/ruby/tests/basic.rb +1653 -0
  133. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsAnchorAlias.yml +51 -0
  134. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsBasicTests.yml +282 -0
  135. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsBlockMapping.yml +78 -0
  136. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsBlockSequence.yml +0 -0
  137. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsDocumentSeparator.yml +102 -0
  138. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsErrorTests.yml +23 -0
  139. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsFlowCollections.yml +73 -0
  140. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsFoldedScalars.yml +215 -0
  141. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsMapInSeq.yml +0 -0
  142. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsNullsAndEmpties.yml +66 -0
  143. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsRubyTests.yml +182 -0
  144. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsSpecificationExamples.yml +2699 -0
  145. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsTypeTransfers.yml +265 -0
  146. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsYpath.yml +221 -0
  147. data/test/sample_files/syck-0.55/ext/ruby/yts/cookbook.rb +159 -0
  148. data/test/sample_files/syck-0.55/ext/ruby/yts/index.yml +10 -0
  149. data/test/sample_files/syck-0.55/ext/ruby/yts/yts.rb +193 -0
  150. data/test/sample_files/syck-0.55/lib/Makefile +497 -0
  151. data/test/sample_files/syck-0.55/lib/Makefile.am +27 -0
  152. data/test/sample_files/syck-0.55/lib/Makefile.in +497 -0
  153. data/test/sample_files/syck-0.55/lib/bytecode.c +1170 -0
  154. data/test/sample_files/syck-0.55/lib/bytecode.re +525 -0
  155. data/test/sample_files/syck-0.55/lib/emitter.c +1224 -0
  156. data/test/sample_files/syck-0.55/lib/gram.c +1894 -0
  157. data/test/sample_files/syck-0.55/lib/gram.h +79 -0
  158. data/test/sample_files/syck-0.55/lib/gram.output +2005 -0
  159. data/test/sample_files/syck-0.55/lib/gram.y +481 -0
  160. data/test/sample_files/syck-0.55/lib/handler.c +174 -0
  161. data/test/sample_files/syck-0.55/lib/implicit.c +2989 -0
  162. data/test/sample_files/syck-0.55/lib/implicit.re +206 -0
  163. data/test/sample_files/syck-0.55/lib/node.c +407 -0
  164. data/test/sample_files/syck-0.55/lib/syck.c +504 -0
  165. data/test/sample_files/syck-0.55/lib/syck.h +458 -0
  166. data/test/sample_files/syck-0.55/lib/syck_st.c +577 -0
  167. data/test/sample_files/syck-0.55/lib/syck_st.h +46 -0
  168. data/test/sample_files/syck-0.55/lib/token.c +2707 -0
  169. data/test/sample_files/syck-0.55/lib/token.re +1139 -0
  170. data/test/sample_files/syck-0.55/lib/yaml2byte.c +250 -0
  171. data/test/sample_files/syck-0.55/lib/yamlbyte.h +170 -0
  172. data/test/sample_files/syck-0.55/stamp-h1 +1 -0
  173. data/test/sample_files/syck-0.55/tests/Basic.c +141 -0
  174. data/test/sample_files/syck-0.55/tests/CuTest.c +294 -0
  175. data/test/sample_files/syck-0.55/tests/CuTest.h +84 -0
  176. data/test/sample_files/syck-0.55/tests/Emit.c +87 -0
  177. data/test/sample_files/syck-0.55/tests/Makefile +480 -0
  178. data/test/sample_files/syck-0.55/tests/Makefile.am +13 -0
  179. data/test/sample_files/syck-0.55/tests/Makefile.in +480 -0
  180. data/test/sample_files/syck-0.55/tests/Parse.c +208 -0
  181. data/test/sample_files/syck-0.55/tests/YTS.c +2310 -0
  182. data/test/sample_files/syck-0.55/tests/YTS.c.erb +326 -0
  183. data/test/sample_files/syck-0.55/tests/YTS.c.rb +44 -0
  184. data/test/test_availability.rb +68 -0
  185. data/test/test_generator.rb +74 -0
  186. metadata +252 -0
@@ -0,0 +1,161 @@
1
+ #
2
+ # vim:sw=4:ts=4
3
+ # $Id: okay.rb,v 1.3 2003/10/13 01:54:00 whythluckystiff Exp $
4
+ #
5
+ # Okay Project
6
+ #
7
+ require 'yaml'
8
+
9
+ module Okay
10
+
11
+ @@type_registry = {
12
+ 'boolean' => nil,
13
+ 'str' => nil,
14
+ 'int' => nil,
15
+ 'null' => nil,
16
+ 'float' => nil,
17
+ 'seq' => nil,
18
+ 'map' => nil
19
+ }
20
+
21
+ class Error < StandardError; end
22
+
23
+ # Transfer methods for okay types
24
+ TRANSFER_TYPES = {}
25
+ OKAY_TYPE_DOMAIN = 'okay.yaml.org,2002'
26
+ OKAY_TYPE_REGEXP = /^tag:#{ Regexp::quote( OKAY_TYPE_DOMAIN ) }:([^;]+)((?:;\w+)*)$/
27
+
28
+ #
29
+ # Base class for Okay types
30
+ # All types should inherit this class to use modules
31
+ #
32
+ class ModuleBase
33
+ attr_accessor :modules
34
+ end
35
+
36
+ #
37
+ # Quick Okay type handler, handles modules
38
+ #
39
+ def Okay.add_type( type_name, &transfer_proc )
40
+ type_re = /^(#{Regexp::quote( type_name )})((?:;\w+)*)$/
41
+ Okay::TRANSFER_TYPES[ type_name ] = transfer_proc
42
+ YAML.add_domain_type( OKAY_TYPE_DOMAIN, type_re ) { |type, val|
43
+ type, mods = OKAY_TYPE_REGEXP.match( type ).to_a[1,2]
44
+ unless mods.to_s.empty?
45
+ mod_re = /^(#{ mods.slice( 1..-1 ).gsub( /;/, '|' ) });/
46
+ modules = {}
47
+ val.reject! { |k, v|
48
+ if k =~ mod_re
49
+ modules[ $1 ] ||= {}
50
+ modules[ $1 ][ $' ] = v
51
+ true
52
+ else
53
+ false
54
+ end
55
+ }
56
+ end
57
+ Okay::TRANSFER_TYPES[ type ].call( type, val, modules )
58
+ }
59
+ end
60
+
61
+ def Okay.object_maker( obj_class, val, modules )
62
+ obj = YAML.object_maker( obj_class, val )
63
+ unless obj.respond_to?( :modules= )
64
+ raise Okay::Error, "Modules #{modules.keys.join( ',' )} can't be handled by class #{obj_class}" if modules
65
+ end
66
+ obj.modules = modules
67
+ obj
68
+ end
69
+
70
+ def Okay.load_schema( schema )
71
+ schema = YAML::load( schema )
72
+ schema.each { |k,v|
73
+ @@type_registry[k] = v['schema']
74
+ }
75
+ end
76
+
77
+ def Okay.schema( type_name )
78
+ @@type_registry[type_name]
79
+ end
80
+
81
+ def Okay.validate_node( node )
82
+ type, mods = OKAY_TYPE_REGEXP.match( node.type_id ).to_a[1,2]
83
+ unless @@type_registry.has_key?( type )
84
+ raise Okay::Error, "Type `#{type}' not found in loaded schema."
85
+ end
86
+ return true if @@type_registry[ type ].nil?
87
+ node_vs_schema( @@type_registry[ type ], node, [], true )
88
+ end
89
+
90
+ def Okay.node_vs_schema( schema, node, depth, head )
91
+ #
92
+ # Head type can be matched against a core type
93
+ #
94
+ type_id = head ? node.kind : node.type_id
95
+ type_id = node.kind if type_id.empty?
96
+ if type_id =~ /^okay\//
97
+ type_id, mods = OKAY_TYPE_REGEXP.match( type_id ).to_a[1,2]
98
+ end
99
+ if schema.has_key?( type_id )
100
+ attr = schema[ type_id ]
101
+ else
102
+ raise Okay::Error, "Node of type !#{type_id} invalid at /" + depth.join( "/" )
103
+ end
104
+
105
+ if @@type_registry[ type_id ]
106
+ node_vs_schema( @@type_registry[ type_id ], node, depth, true )
107
+ end
108
+
109
+ #
110
+ # Descend and match types of nodes
111
+ #
112
+ if attr
113
+ attr.each { |prop, prop_schema|
114
+ #
115
+ # Mini-paths
116
+ #
117
+ if prop =~ /^\//
118
+ key = $'
119
+ if key == "*"
120
+ node.children_with_index.each { |c|
121
+ node_vs_schema( prop_schema, c[0], depth + [c[1]], false )
122
+ }
123
+ else
124
+ if node[key]
125
+ child = node[key]
126
+ node_vs_schema( prop_schema, child, depth + [key], false )
127
+ else
128
+ unless Array === attr['optional'] and attr['optional'].include?( "/" + key )
129
+ raise Okay::Error, "No key '#{key}' found at /" + depth.join( "/" )
130
+ end
131
+ end
132
+ end
133
+ end
134
+ }
135
+ else
136
+ end
137
+ return true
138
+ end
139
+
140
+ def Okay.make_schema_flexhash( type_root )
141
+ type_root = YAML::transfer( 'tag:ruby.yaml.org,2002:flexhash', type_root )
142
+ type_root.collect! { |e|
143
+ if Hash === e[1]
144
+ e[1].each { |k,v|
145
+ if k =~ /^\// and Array === v
146
+ e[1][k] = make_schema_flexhash( v )
147
+ end
148
+ }
149
+ end
150
+ e
151
+ }
152
+ type_root
153
+ end
154
+
155
+ Okay.add_type( 'schema' ) { |type, val, modules|
156
+ val.each { |k,v|
157
+ v['schema'] = make_schema_flexhash( v['schema'] )
158
+ }
159
+ }
160
+
161
+ end
@@ -0,0 +1,69 @@
1
+ #
2
+ # The !okay/news module for YAML.rb
3
+ #
4
+ require 'okay'
5
+
6
+ module Okay
7
+
8
+ class News < ModuleBase
9
+ attr_accessor :title, :link, :description, :updatePeriod, :items
10
+ def to_yaml_properties
11
+ [ '@title', '@link', '@description', '@updatePeriod', '@items' ]
12
+ end
13
+ def to_yaml_type
14
+ "!okay/news"
15
+ end
16
+ end
17
+
18
+ Okay.add_type( "news" ) { |type, val, modules|
19
+ Okay.object_maker( Okay::News, val, modules )
20
+ }
21
+
22
+ class NewsItem < ModuleBase
23
+ attr_accessor :title, :link, :description, :pubTime
24
+ def to_yaml_properties
25
+ [ '@title', '@link', '@description', '@pubTime' ]
26
+ end
27
+ def to_yaml_type
28
+ "!okay/news/item"
29
+ end
30
+ end
31
+
32
+ Okay.add_type( "news/item" ) { |type, val, modules|
33
+ Okay.object_maker( Okay::NewsItem, val, modules )
34
+ }
35
+
36
+ end
37
+
38
+ Okay.load_schema( <<EOY )
39
+
40
+ # Schema for Okay::News types
41
+ --- %YAML:1.0 !okay/schema
42
+ okay/news:
43
+ description: >
44
+ Inspired by RSS, more limited...
45
+ examples: >
46
+ If I had a news site...
47
+ schema:
48
+ - map:
49
+ /title: [ str ]
50
+ /link: [ str ]
51
+ /description: [ str ]
52
+ /updatePeriod: [ str ]
53
+ /items:
54
+ - seq: { /*: [ okay/news/item ] }
55
+
56
+ okay/news/item:
57
+ description: >
58
+ Inside okay/news lies...
59
+ examples: >
60
+ See okay/news examples...
61
+ schema:
62
+ - map:
63
+ /title: [ str ]
64
+ /pubTime: [ time ]
65
+ /link: [ str ]
66
+ /description: [ str ]
67
+ optional: [ /title ]
68
+
69
+ EOY
@@ -0,0 +1,434 @@
1
+ #
2
+ # The !okay/rpc module for YAML.rb
3
+ # Specification at http://wiki.yaml.org/yamlwiki/OkayRpcProtocol
4
+ #
5
+ require 'okay'
6
+ require 'net/http'
7
+
8
+ module Okay
9
+ module RPC
10
+
11
+ VERSION = '0.06'
12
+
13
+ class Method
14
+ attr_accessor :methodName, :params
15
+ def initialize( mn, p )
16
+ @methodName = mn
17
+ @params = p
18
+ end
19
+ def to_yaml( opts = {} )
20
+ YAML::quick_emit( self.id, opts ) { |out|
21
+ out.map( "!okay/rpc/method" ) { |map|
22
+ map.add( self.methodName, self.params )
23
+ }
24
+ }
25
+ end
26
+ end
27
+
28
+ YAML.add_domain_type( "okay.yaml.org,2002", "rpc/method" ) { |type, val|
29
+ if val.class == Hash and val.length == 1
30
+ val = val.to_a.first
31
+ RPC::Method.new( val[0], val[1] )
32
+ end
33
+ }
34
+
35
+ class Fault
36
+ attr_accessor :code, :message
37
+ def initialize( c, m )
38
+ @code = c
39
+ @message = m
40
+ end
41
+ def to_yaml( opts = {} )
42
+ YAML::quick_emit( self.id, opts ) { |out|
43
+ out.map( "!okay/rpc/fault" ) { |map|
44
+ map.add( self.code, self.message )
45
+ }
46
+ }
47
+ end
48
+ end
49
+
50
+ YAML.add_domain_type( "okay.yaml.org,2002", "rpc/fault" ) { |type, val|
51
+ if val.class == Hash and val.length == 1
52
+ val = val.to_a.first
53
+ Fault.new( val[0], val[1] )
54
+ end
55
+ }
56
+
57
+ class Client
58
+ USER_AGENT = "Okay::RPC::Client (Ruby #{RUBY_VERSION})"
59
+ def initialize(host=nil, path=nil, port=nil, proxy_host=nil, proxy_port=nil,
60
+ user=nil, password=nil, use_ssl=nil, timeout=nil)
61
+
62
+ @host = host || "localhost"
63
+ @path = path || "/okayRpc/"
64
+ @proxy_host = proxy_host
65
+ @proxy_port = proxy_port
66
+ @proxy_host ||= 'localhost' if @proxy_port != nil
67
+ @proxy_port ||= 8080 if @proxy_host != nil
68
+ @use_ssl = use_ssl || false
69
+ @timeout = timeout || 30
70
+ @queue = YAML::Stream.new( :UseHeader => true )
71
+
72
+ if use_ssl
73
+ require "net/https"
74
+ @port = port || 443
75
+ else
76
+ @port = port || 80
77
+ end
78
+
79
+ @user, @password = user, password
80
+
81
+ set_auth
82
+
83
+ # convert ports to integers
84
+ @port = @port.to_i if @port != nil
85
+ @proxy_port = @proxy_port.to_i if @proxy_port != nil
86
+
87
+ # HTTP object for synchronous calls
88
+ Net::HTTP.version_1_2
89
+ @http = Net::HTTP.new(@host, @port, @proxy_host, @proxy_port)
90
+ @http.use_ssl = @use_ssl if @use_ssl
91
+ @http.read_timeout = @timeout
92
+ @http.open_timeout = @timeout
93
+
94
+ @parser = nil
95
+ @create = nil
96
+ end
97
+
98
+ # Attribute Accessors -------------------------------------------------------------------
99
+
100
+ attr_reader :timeout, :user, :password
101
+
102
+ def timeout=(new_timeout)
103
+ @timeout = new_timeout
104
+ @http.read_timeout = @timeout
105
+ @http.open_timeout = @timeout
106
+ end
107
+
108
+ def user=(new_user)
109
+ @user = new_user
110
+ set_auth
111
+ end
112
+
113
+ def password=(new_password)
114
+ @password = new_password
115
+ set_auth
116
+ end
117
+
118
+ # Call methods --------------------------------------------------------------
119
+
120
+ def call(method, *args)
121
+ meth = Method.new( method, args )
122
+ YAML::load( do_rpc(meth.to_yaml, false) )
123
+ end
124
+
125
+ def qcall(method, *args)
126
+ @queue.add( Method.new( method, args ) )
127
+ end
128
+
129
+ def qrun
130
+ ret = YAML.load_stream( do_rpc( @queue.emit, false ) )
131
+ @queue = YAML::Stream.new( :UseHeader => true )
132
+ ret
133
+ end
134
+
135
+ private # ----------------------------------------------------------
136
+
137
+ def set_auth
138
+ if @user.nil?
139
+ @auth = nil
140
+ else
141
+ a = "#@user"
142
+ a << ":#@password" if @password != nil
143
+ @auth = ("Basic " + [a].pack("m")).chomp
144
+ end
145
+ end
146
+
147
+ def do_rpc(request, async=false)
148
+ header = {
149
+ "User-Agent" => USER_AGENT,
150
+ "Content-Type" => "text/yaml",
151
+ "Content-Length" => request.size.to_s,
152
+ "Connection" => (async ? "close" : "keep-alive")
153
+ }
154
+
155
+ if @auth != nil
156
+ # add authorization header
157
+ header["Authorization"] = @auth
158
+ end
159
+
160
+ if async
161
+ # use a new HTTP object for each call
162
+ Net::HTTP.version_1_2
163
+ http = Net::HTTP.new(@host, @port, @proxy_host, @proxy_port)
164
+ http.use_ssl = @use_ssl if @use_ssl
165
+ http.read_timeout = @timeout
166
+ http.open_timeout = @timeout
167
+ else
168
+ # reuse the HTTP object for each call => connection alive is possible
169
+ http = @http
170
+ end
171
+
172
+ # post request
173
+ resp = http.post2(@path, request, header)
174
+ data = resp.body
175
+ http.finish if async
176
+
177
+ if resp.code == "401"
178
+ # Authorization Required
179
+ raise "Authorization failed.\nHTTP-Error: #{resp.code} #{resp.message}"
180
+ elsif resp.code[0,1] != "2"
181
+ raise "HTTP-Error: #{resp.code} #{resp.message}"
182
+ end
183
+
184
+ if resp["Content-Type"] != "text/yaml"
185
+ raise "Wrong content-type [#{resp['Content-Type']}]: \n#{data}"
186
+ end
187
+
188
+ expected = resp["Content-Length"] || "<unknown>"
189
+ if data.nil? or data.size == 0
190
+ raise "Wrong size. Was #{data.size}, should be #{expected}"
191
+ elsif expected.to_i != data.size and resp["Transfer-Encoding"].nil?
192
+ raise "Wrong size. Was #{data.size}, should be #{expected}"
193
+ end
194
+
195
+ return data
196
+ end
197
+
198
+ end
199
+
200
+ class BasicServer
201
+ def initialize
202
+ @handlers = {}
203
+ @aboutHash = {
204
+ 'name' => 'An !okay/rpc server.',
205
+ 'uri' => nil,
206
+ 'version' => VERSION,
207
+ 'authors' => nil,
208
+ 'about' => "Welcome to the !okay/rpc server."
209
+ }
210
+ add_introspection
211
+ end
212
+ def name( str )
213
+ @aboutHash['name']
214
+ end
215
+ def name=( str )
216
+ @aboutHash['name'] = str
217
+ end
218
+ def about
219
+ @aboutHash['about']
220
+ end
221
+ def about=( str )
222
+ @aboutHash['about'] = str.strip.gsub( /^ +/, '' ).gsub( /\n(\n*)/, ' \1' )
223
+ end
224
+ def uri( str )
225
+ @aboutHash['uri']
226
+ end
227
+ def uri=( str )
228
+ @aboutHash['uri'] = str
229
+ end
230
+ def add_author( name, email, url )
231
+ @aboutHash['authors'] ||= []
232
+ @aboutHash['authors'] << {
233
+ 'name' => name,
234
+ 'email' => email,
235
+ 'url' => url
236
+ }
237
+ end
238
+ def add_handler( methodName, sig, doc, &block )
239
+ @handlers[ methodName ] = {
240
+ :signature => sig,
241
+ :help => doc,
242
+ :block => block
243
+ }
244
+ end
245
+ def get_handler( methodName, prop )
246
+ unless @handlers.has_key?( methodName )
247
+ Fault.new( 101, "No method ''#{methodName}'' available." )
248
+ else
249
+ @handlers[ methodName ][ prop ]
250
+ end
251
+ end
252
+ def dispatch( meth )
253
+ b = get_handler( meth.methodName, :block )
254
+ return b if b.is_a? Fault
255
+ b.call( meth )
256
+ end
257
+ def process( meth_yml )
258
+ s = YAML::Stream.new( :UseHeader => true )
259
+ YAML::load_documents( meth_yml ) { |doc|
260
+ s.add( dispatch( doc ) )
261
+ }
262
+ s.emit
263
+ end
264
+
265
+ private
266
+
267
+ def add_introspection
268
+
269
+ add_handler(
270
+ "system.about", %w(map),
271
+ "Provides a short description of this !okay/rpc server's intent."
272
+ ) {
273
+ @aboutHash
274
+ }
275
+
276
+ add_handler(
277
+ "system.getCapabilities", %w(map),
278
+ "Describes this server's capabilities, including version of " +
279
+ "!okay/rpc available and YAML implementation."
280
+ ) {
281
+ {
282
+ 'okay/rpc' =>
283
+ { 'version' => Okay::RPC::VERSION,
284
+ 'id' => 'YAML.rb Okay::RPC',
285
+ 'url' => 'http://wiki.yaml.org/yamlwiki/OkayRpcProtocol'
286
+ },
287
+ 'yaml' =>
288
+ { 'version' => YAML::VERSION,
289
+ 'id' => 'YAML.rb',
290
+ 'url' => 'http://yaml4r.sf.net/'
291
+ },
292
+ 'sys' =>
293
+ { 'version' => Kernel::RUBY_VERSION,
294
+ 'id' => Kernel::RUBY_PLATFORM
295
+ }
296
+ }
297
+ }
298
+
299
+ add_handler(
300
+ "system.listMethods", %w(seq),
301
+ "Lists the available methods for this !okay/rpc server."
302
+ ) {
303
+ @handlers.keys.sort
304
+ }
305
+
306
+ add_handler(
307
+ "system.methodSignature", %w(seq str),
308
+ "Returns a method signature."
309
+ ) { |meth|
310
+ get_handler( meth.params[0], :signature )
311
+ }
312
+
313
+ add_handler(
314
+ "system.methodHelp", %w(str str),
315
+ "Returns help on using this method."
316
+ ) { |meth|
317
+ get_handler( meth.params[0], :help )
318
+ }
319
+
320
+ add_handler(
321
+ "system.methodBlank", %w(str str),
322
+ "Returns a blank method."
323
+ ) { |meth|
324
+ sig = get_handler( meth.params[0], :signature )
325
+ unless sig.is_a? Fault
326
+ "--- !okay/rpc/method\n#{meth.params[0]}:\n" +
327
+ sig[1..-1].collect { |type| " - !#{type}" }.join( "\n" )
328
+ else
329
+ sig
330
+ end
331
+ }
332
+
333
+ end
334
+ end
335
+
336
+ class ModRubyServer < BasicServer
337
+
338
+ def initialize(*a)
339
+ @ap = Apache::request
340
+ super(*a)
341
+ url ||= @ap.uri
342
+ end
343
+
344
+ def serve
345
+ catch(:exit_serve) {
346
+ header = {}
347
+ hdr_in_proc = proc {|key, value| header[key.capitalize] = value}
348
+ if @ap.respond_to? :headers_in
349
+ @ap.headers_in.each( &hdr_in_proc )
350
+ else
351
+ @ap.each_header( &hdr_in_proc )
352
+ end
353
+
354
+ length = header['Content-length'].to_i
355
+
356
+ http_error(405, "Method Not Allowed") unless @ap.request_method == "POST"
357
+ http_error(400, "Bad Request") unless header['Content-type'] == "text/yaml"
358
+ http_error(411, "Length Required") unless length > 0
359
+
360
+ # TODO: do we need a call to binmode?
361
+ @ap.binmode
362
+ data = @ap.read(length)
363
+
364
+ http_error(400, "Bad Request") if data.nil? or data.size != length
365
+
366
+ resp =
367
+ begin
368
+ process(data)
369
+ rescue Exception => e
370
+ Fault.new(101, e.message).to_yaml
371
+ end
372
+ http_write(resp, 200, "Content-type" => "text/yaml")
373
+ }
374
+ end
375
+
376
+
377
+ private
378
+
379
+ def http_error(status, message)
380
+ err = "#{status} #{message}"
381
+ msg = <<-"MSGEND"
382
+ <html>
383
+ <head>
384
+ <title>#{err}</title>
385
+ </head>
386
+ <body>
387
+ <h1>#{err}</h1>
388
+ <p>Unexpected error occured while processing !okay/rpc request!</p>
389
+ </body>
390
+ </html>
391
+ MSGEND
392
+
393
+ http_write(msg, status, "Status" => err, "Content-type" => "text/html")
394
+ throw :exit_serve # exit from the #serve method
395
+ end
396
+
397
+ def http_write(body, status, header)
398
+ h = {}
399
+ header.each {|key, value| h[key.to_s.capitalize] = value}
400
+ h['Status'] ||= "200 OK"
401
+ h['Content-length'] ||= body.size.to_s
402
+
403
+ h.each do |key, value|
404
+ if @ap.respond_to? :headers_out
405
+ @ap.headers_out[key] = value
406
+ else
407
+ @ap[key] = value
408
+ end
409
+ end
410
+ @ap.content_type = h["Content-type"]
411
+ @ap.status = status.to_i
412
+ @ap.send_http_header
413
+
414
+ @ap.print body
415
+ end
416
+ end
417
+
418
+ end
419
+ end
420
+
421
+ Okay.load_schema( <<EOY )
422
+
423
+ --- %YAML:1.0 !okay/schema
424
+ okay/rpc/method:
425
+ description: >
426
+ XML-RPC for YAML.
427
+ examples: >
428
+ Testing
429
+ schema:
430
+ - map:
431
+ /*: [ seq ]
432
+ length: 1
433
+
434
+ EOY