mkrf 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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