csd 0.0.15 → 0.0.16

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 (256) hide show
  1. data/.gitignore +1 -0
  2. data/COPYING +367 -0
  3. data/Rakefile +10 -10
  4. data/VERSION +1 -1
  5. data/bin/ai +19 -0
  6. data/csd.gemspec +257 -35
  7. data/lib/active_support.rb +75 -0
  8. data/lib/active_support/all.rb +3 -0
  9. data/lib/active_support/backtrace_cleaner.rb +94 -0
  10. data/lib/active_support/base64.rb +42 -0
  11. data/lib/active_support/basic_object.rb +21 -0
  12. data/lib/active_support/benchmarkable.rb +60 -0
  13. data/lib/active_support/buffered_logger.rb +132 -0
  14. data/lib/active_support/builder.rb +6 -0
  15. data/lib/active_support/cache.rb +626 -0
  16. data/lib/active_support/cache/compressed_mem_cache_store.rb +13 -0
  17. data/lib/active_support/cache/file_store.rb +188 -0
  18. data/lib/active_support/cache/mem_cache_store.rb +191 -0
  19. data/lib/active_support/cache/memory_store.rb +159 -0
  20. data/lib/active_support/cache/strategy/local_cache.rb +164 -0
  21. data/lib/active_support/cache/synchronized_memory_store.rb +11 -0
  22. data/lib/active_support/callbacks.rb +600 -0
  23. data/lib/active_support/concern.rb +29 -0
  24. data/lib/active_support/configurable.rb +36 -0
  25. data/lib/active_support/core_ext.rb +3 -0
  26. data/lib/active_support/core_ext/array.rb +7 -0
  27. data/lib/active_support/core_ext/array/access.rb +46 -0
  28. data/lib/active_support/core_ext/array/conversions.rb +164 -0
  29. data/lib/active_support/core_ext/array/extract_options.rb +29 -0
  30. data/lib/active_support/core_ext/array/grouping.rb +100 -0
  31. data/lib/active_support/core_ext/array/random_access.rb +20 -0
  32. data/lib/active_support/core_ext/array/uniq_by.rb +17 -0
  33. data/lib/active_support/core_ext/array/wrap.rb +22 -0
  34. data/lib/active_support/core_ext/benchmark.rb +7 -0
  35. data/lib/active_support/core_ext/big_decimal.rb +1 -0
  36. data/lib/active_support/core_ext/big_decimal/conversions.rb +27 -0
  37. data/lib/active_support/core_ext/cgi.rb +1 -0
  38. data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +19 -0
  39. data/lib/active_support/core_ext/class.rb +4 -0
  40. data/lib/active_support/core_ext/class/attribute.rb +67 -0
  41. data/lib/active_support/core_ext/class/attribute_accessors.rb +63 -0
  42. data/lib/active_support/core_ext/class/delegating_attributes.rb +44 -0
  43. data/lib/active_support/core_ext/class/inheritable_attributes.rb +232 -0
  44. data/lib/active_support/core_ext/class/subclasses.rb +55 -0
  45. data/lib/active_support/core_ext/date/acts_like.rb +8 -0
  46. data/lib/active_support/core_ext/date/calculations.rb +240 -0
  47. data/lib/active_support/core_ext/date/conversions.rb +99 -0
  48. data/lib/active_support/core_ext/date/freeze.rb +31 -0
  49. data/lib/active_support/core_ext/date_time/acts_like.rb +13 -0
  50. data/lib/active_support/core_ext/date_time/calculations.rb +113 -0
  51. data/lib/active_support/core_ext/date_time/conversions.rb +102 -0
  52. data/lib/active_support/core_ext/date_time/zones.rb +17 -0
  53. data/lib/active_support/core_ext/enumerable.rb +119 -0
  54. data/lib/active_support/core_ext/exception.rb +3 -0
  55. data/lib/active_support/core_ext/file.rb +2 -0
  56. data/lib/active_support/core_ext/file/atomic.rb +41 -0
  57. data/lib/active_support/core_ext/file/path.rb +5 -0
  58. data/lib/active_support/core_ext/float.rb +1 -0
  59. data/lib/active_support/core_ext/float/rounding.rb +19 -0
  60. data/lib/active_support/core_ext/hash.rb +8 -0
  61. data/lib/active_support/core_ext/hash/conversions.rb +150 -0
  62. data/lib/active_support/core_ext/hash/deep_merge.rb +16 -0
  63. data/lib/active_support/core_ext/hash/diff.rb +13 -0
  64. data/lib/active_support/core_ext/hash/except.rb +24 -0
  65. data/lib/active_support/core_ext/hash/indifferent_access.rb +14 -0
  66. data/lib/active_support/core_ext/hash/keys.rb +45 -0
  67. data/lib/active_support/core_ext/hash/reverse_merge.rb +28 -0
  68. data/lib/active_support/core_ext/hash/slice.rb +38 -0
  69. data/lib/active_support/core_ext/integer.rb +3 -0
  70. data/lib/active_support/core_ext/integer/inflections.rb +14 -0
  71. data/lib/active_support/core_ext/integer/multiple.rb +6 -0
  72. data/lib/active_support/core_ext/integer/time.rb +39 -0
  73. data/lib/active_support/core_ext/kernel.rb +5 -0
  74. data/lib/active_support/core_ext/kernel/agnostics.rb +11 -0
  75. data/lib/active_support/core_ext/kernel/debugger.rb +16 -0
  76. data/lib/active_support/core_ext/kernel/reporting.rb +62 -0
  77. data/lib/active_support/core_ext/kernel/requires.rb +26 -0
  78. data/lib/active_support/core_ext/kernel/singleton_class.rb +13 -0
  79. data/lib/active_support/core_ext/load_error.rb +23 -0
  80. data/lib/active_support/core_ext/logger.rb +146 -0
  81. data/lib/active_support/core_ext/module.rb +12 -0
  82. data/lib/active_support/core_ext/module/aliasing.rb +70 -0
  83. data/lib/active_support/core_ext/module/anonymous.rb +24 -0
  84. data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +31 -0
  85. data/lib/active_support/core_ext/module/attr_internal.rb +32 -0
  86. data/lib/active_support/core_ext/module/attribute_accessors.rb +66 -0
  87. data/lib/active_support/core_ext/module/delegation.rb +146 -0
  88. data/lib/active_support/core_ext/module/deprecation.rb +9 -0
  89. data/lib/active_support/core_ext/module/introspection.rb +88 -0
  90. data/lib/active_support/core_ext/module/method_names.rb +14 -0
  91. data/lib/active_support/core_ext/module/reachable.rb +10 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +6 -0
  93. data/lib/active_support/core_ext/module/synchronization.rb +42 -0
  94. data/lib/active_support/core_ext/name_error.rb +18 -0
  95. data/lib/active_support/core_ext/numeric.rb +2 -0
  96. data/lib/active_support/core_ext/numeric/bytes.rb +44 -0
  97. data/lib/active_support/core_ext/numeric/time.rb +77 -0
  98. data/lib/active_support/core_ext/object.rb +14 -0
  99. data/lib/active_support/core_ext/object/acts_like.rb +10 -0
  100. data/lib/active_support/core_ext/object/blank.rb +76 -0
  101. data/lib/active_support/core_ext/object/conversions.rb +4 -0
  102. data/lib/active_support/core_ext/object/duplicable.rb +65 -0
  103. data/lib/active_support/core_ext/object/extending.rb +11 -0
  104. data/lib/active_support/core_ext/object/instance_variables.rb +67 -0
  105. data/lib/active_support/core_ext/object/misc.rb +2 -0
  106. data/lib/active_support/core_ext/object/returning.rb +42 -0
  107. data/lib/active_support/core_ext/object/to_param.rb +49 -0
  108. data/lib/active_support/core_ext/object/to_query.rb +27 -0
  109. data/lib/active_support/core_ext/object/try.rb +36 -0
  110. data/lib/active_support/core_ext/object/with_options.rb +26 -0
  111. data/lib/active_support/core_ext/proc.rb +14 -0
  112. data/lib/active_support/core_ext/process.rb +1 -0
  113. data/lib/active_support/core_ext/process/daemon.rb +23 -0
  114. data/lib/active_support/core_ext/range.rb +4 -0
  115. data/lib/active_support/core_ext/range/blockless_step.rb +29 -0
  116. data/lib/active_support/core_ext/range/conversions.rb +21 -0
  117. data/lib/active_support/core_ext/range/include_range.rb +21 -0
  118. data/lib/active_support/core_ext/range/overlaps.rb +8 -0
  119. data/lib/active_support/core_ext/regexp.rb +5 -0
  120. data/lib/active_support/core_ext/rexml.rb +46 -0
  121. data/lib/active_support/core_ext/string.rb +12 -0
  122. data/lib/active_support/core_ext/string/access.rb +99 -0
  123. data/lib/active_support/core_ext/string/behavior.rb +7 -0
  124. data/lib/active_support/core_ext/string/conversions.rb +61 -0
  125. data/lib/active_support/core_ext/string/encoding.rb +11 -0
  126. data/lib/active_support/core_ext/string/exclude.rb +6 -0
  127. data/lib/active_support/core_ext/string/filters.rb +49 -0
  128. data/lib/active_support/core_ext/string/inflections.rb +149 -0
  129. data/lib/active_support/core_ext/string/interpolation.rb +2 -0
  130. data/lib/active_support/core_ext/string/multibyte.rb +72 -0
  131. data/lib/active_support/core_ext/string/output_safety.rb +109 -0
  132. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -0
  133. data/lib/active_support/core_ext/string/xchar.rb +18 -0
  134. data/lib/active_support/core_ext/time/acts_like.rb +8 -0
  135. data/lib/active_support/core_ext/time/calculations.rb +282 -0
  136. data/lib/active_support/core_ext/time/conversions.rb +85 -0
  137. data/lib/active_support/core_ext/time/marshal.rb +56 -0
  138. data/lib/active_support/core_ext/time/publicize_conversion_methods.rb +10 -0
  139. data/lib/active_support/core_ext/time/zones.rb +78 -0
  140. data/lib/active_support/core_ext/uri.rb +22 -0
  141. data/lib/active_support/dependencies.rb +628 -0
  142. data/lib/active_support/dependencies/autoload.rb +50 -0
  143. data/lib/active_support/deprecation.rb +18 -0
  144. data/lib/active_support/deprecation/behaviors.rb +38 -0
  145. data/lib/active_support/deprecation/method_wrappers.rb +29 -0
  146. data/lib/active_support/deprecation/proxy_wrappers.rb +74 -0
  147. data/lib/active_support/deprecation/reporting.rb +56 -0
  148. data/lib/active_support/duration.rb +105 -0
  149. data/lib/active_support/gzip.rb +25 -0
  150. data/lib/active_support/hash_with_indifferent_access.rb +145 -0
  151. data/lib/active_support/i18n.rb +8 -0
  152. data/lib/active_support/inflections.rb +56 -0
  153. data/lib/active_support/inflector.rb +7 -0
  154. data/lib/active_support/inflector/inflections.rb +211 -0
  155. data/lib/active_support/inflector/methods.rb +141 -0
  156. data/lib/active_support/inflector/transliterate.rb +97 -0
  157. data/lib/active_support/json.rb +2 -0
  158. data/lib/active_support/json/backends/jsongem.rb +43 -0
  159. data/lib/active_support/json/backends/yajl.rb +40 -0
  160. data/lib/active_support/json/backends/yaml.rb +90 -0
  161. data/lib/active_support/json/decoding.rb +51 -0
  162. data/lib/active_support/json/encoding.rb +254 -0
  163. data/lib/active_support/json/variable.rb +11 -0
  164. data/lib/active_support/lazy_load_hooks.rb +27 -0
  165. data/lib/active_support/locale/en.yml +36 -0
  166. data/lib/active_support/memoizable.rb +103 -0
  167. data/lib/active_support/message_encryptor.rb +71 -0
  168. data/lib/active_support/message_verifier.rb +62 -0
  169. data/lib/active_support/multibyte.rb +44 -0
  170. data/lib/active_support/multibyte/chars.rb +480 -0
  171. data/lib/active_support/multibyte/exceptions.rb +8 -0
  172. data/lib/active_support/multibyte/unicode.rb +393 -0
  173. data/lib/active_support/multibyte/utils.rb +60 -0
  174. data/lib/active_support/notifications.rb +81 -0
  175. data/lib/active_support/notifications/fanout.rb +93 -0
  176. data/lib/active_support/notifications/instrumenter.rb +56 -0
  177. data/lib/active_support/option_merger.rb +25 -0
  178. data/lib/active_support/ordered_hash.rb +158 -0
  179. data/lib/active_support/ordered_options.rb +27 -0
  180. data/lib/active_support/railtie.rb +100 -0
  181. data/lib/active_support/rescuable.rb +114 -0
  182. data/lib/active_support/ruby/shim.rb +22 -0
  183. data/lib/active_support/secure_random.rb +199 -0
  184. data/lib/active_support/string_inquirer.rb +21 -0
  185. data/lib/active_support/test_case.rb +42 -0
  186. data/lib/active_support/testing/assertions.rb +82 -0
  187. data/lib/active_support/testing/declarative.rb +40 -0
  188. data/lib/active_support/testing/default.rb +9 -0
  189. data/lib/active_support/testing/deprecation.rb +55 -0
  190. data/lib/active_support/testing/isolation.rb +154 -0
  191. data/lib/active_support/testing/pending.rb +48 -0
  192. data/lib/active_support/testing/performance.rb +455 -0
  193. data/lib/active_support/testing/setup_and_teardown.rb +111 -0
  194. data/lib/active_support/time.rb +34 -0
  195. data/lib/active_support/time/autoload.rb +5 -0
  196. data/lib/active_support/time_with_zone.rb +341 -0
  197. data/lib/active_support/values/time_zone.rb +377 -0
  198. data/lib/active_support/values/unicode_tables.dat +0 -0
  199. data/lib/active_support/version.rb +10 -0
  200. data/lib/active_support/whiny_nil.rb +60 -0
  201. data/lib/active_support/xml_mini.rb +158 -0
  202. data/lib/active_support/xml_mini/jdom.rb +168 -0
  203. data/lib/active_support/xml_mini/libxml.rb +80 -0
  204. data/lib/active_support/xml_mini/libxmlsax.rb +85 -0
  205. data/lib/active_support/xml_mini/nokogiri.rb +78 -0
  206. data/lib/active_support/xml_mini/nokogirisax.rb +83 -0
  207. data/lib/active_support/xml_mini/rexml.rb +129 -0
  208. data/lib/csd.rb +82 -2
  209. data/lib/csd/application.rb +2 -0
  210. data/lib/csd/application/default.rb +51 -0
  211. data/lib/csd/application/default/base.rb +15 -0
  212. data/lib/csd/application/minisip.rb +25 -0
  213. data/lib/csd/application/minisip/about.yml +14 -0
  214. data/lib/csd/application/minisip/base.rb +161 -0
  215. data/lib/csd/application/minisip/error.rb +11 -0
  216. data/lib/csd/application/minisip/options/common.rb +0 -0
  217. data/lib/csd/application/minisip/options/compile.rb +59 -0
  218. data/lib/csd/{applications → application}/minisip/unix/base.rb +10 -11
  219. data/lib/csd/application/opensips/about.yml +2 -0
  220. data/lib/csd/applications.rb +55 -0
  221. data/lib/csd/commands.rb +88 -65
  222. data/lib/csd/error.rb +31 -0
  223. data/lib/csd/extensions.rb +1 -0
  224. data/lib/{extensions → csd/extensions}/core/array.rb +2 -2
  225. data/lib/csd/extensions/core/dir.rb +46 -0
  226. data/lib/{extensions → csd/extensions}/core/file.rb +2 -2
  227. data/lib/{extensions → csd/extensions}/core/object.rb +2 -2
  228. data/lib/csd/extensions/core/option_parser.rb +33 -0
  229. data/lib/{extensions → csd/extensions}/core/pathname.rb +12 -3
  230. data/lib/{extensions → csd/extensions}/core/string.rb +2 -2
  231. data/lib/{extensions → csd/extensions}/gem/platform.rb +6 -2
  232. data/lib/csd/global_open_struct.rb +18 -0
  233. data/lib/csd/options.rb +124 -95
  234. data/lib/csd/path.rb +31 -0
  235. data/lib/csd/ui.rb +1 -0
  236. data/lib/csd/ui/cli.rb +7 -0
  237. data/lib/csd/ui/ui.rb +46 -0
  238. data/lib/csd/version.rb +9 -0
  239. data/lib/term/ansicolor.rb +102 -0
  240. data/lib/term/ansicolor/.keep +0 -0
  241. data/lib/term/ansicolor/version.rb +10 -0
  242. data/test/functional/test_applications.rb +86 -0
  243. data/test/functional/test_commands.rb +42 -29
  244. data/test/functional/test_options.rb +98 -0
  245. data/test/helper.rb +14 -0
  246. data/test/unit/test_dir.rb +38 -0
  247. data/test/unit/test_pathname.rb +32 -0
  248. metadata +253 -40
  249. data/LICENSE +0 -20
  250. data/bin/csd +0 -8
  251. data/lib/csd/applications/base.rb +0 -33
  252. data/lib/csd/applications/minisip/base.rb +0 -125
  253. data/lib/csd/applications/minisip/init.rb +0 -20
  254. data/lib/csd/init.rb +0 -69
  255. data/lib/csd/path_container.rb +0 -15
  256. data/publish +0 -29
@@ -0,0 +1,158 @@
1
+ require 'active_support/core_ext/module/delegation'
2
+
3
+ module ActiveSupport
4
+ # = XmlMini
5
+ #
6
+ # To use the much faster libxml parser:
7
+ # gem 'libxml-ruby', '=0.9.7'
8
+ # XmlMini.backend = 'LibXML'
9
+ module XmlMini
10
+ extend self
11
+
12
+ # This module exists to decorate files deserialized using Hash.from_xml with
13
+ # the <tt>original_filename</tt> and <tt>content_type</tt> methods.
14
+ module FileLike #:nodoc:
15
+ attr_writer :original_filename, :content_type
16
+
17
+ def original_filename
18
+ @original_filename || 'untitled'
19
+ end
20
+
21
+ def content_type
22
+ @content_type || 'application/octet-stream'
23
+ end
24
+ end
25
+
26
+ DEFAULT_ENCODINGS = {
27
+ "binary" => "base64"
28
+ } unless defined?(TYPE_NAMES)
29
+
30
+ TYPE_NAMES = {
31
+ "Symbol" => "symbol",
32
+ "Fixnum" => "integer",
33
+ "Bignum" => "integer",
34
+ "BigDecimal" => "decimal",
35
+ "Float" => "float",
36
+ "TrueClass" => "boolean",
37
+ "FalseClass" => "boolean",
38
+ "Date" => "date",
39
+ "DateTime" => "datetime",
40
+ "Time" => "datetime",
41
+ "Array" => "array",
42
+ "Hash" => "hash"
43
+ } unless defined?(TYPE_NAMES)
44
+
45
+ FORMATTING = {
46
+ "symbol" => Proc.new { |symbol| symbol.to_s },
47
+ "date" => Proc.new { |date| date.to_s(:db) },
48
+ "datetime" => Proc.new { |time| time.xmlschema },
49
+ "binary" => Proc.new { |binary| ActiveSupport::Base64.encode64(binary) },
50
+ "yaml" => Proc.new { |yaml| yaml.to_yaml }
51
+ } unless defined?(FORMATTING)
52
+
53
+ # TODO: use Time.xmlschema instead of Time.parse;
54
+ # use regexp instead of Date.parse
55
+ unless defined?(PARSING)
56
+ PARSING = {
57
+ "symbol" => Proc.new { |symbol| symbol.to_sym },
58
+ "date" => Proc.new { |date| ::Date.parse(date) },
59
+ "datetime" => Proc.new { |time| ::Time.parse(time).utc rescue ::DateTime.parse(time).utc },
60
+ "integer" => Proc.new { |integer| integer.to_i },
61
+ "float" => Proc.new { |float| float.to_f },
62
+ "decimal" => Proc.new { |number| BigDecimal(number) },
63
+ "boolean" => Proc.new { |boolean| %w(1 true).include?(boolean.strip) },
64
+ "string" => Proc.new { |string| string.to_s },
65
+ "yaml" => Proc.new { |yaml| YAML::load(yaml) rescue yaml },
66
+ "base64Binary" => Proc.new { |bin| ActiveSupport::Base64.decode64(bin) },
67
+ "binary" => Proc.new { |bin, entity| _parse_binary(bin, entity) },
68
+ "file" => Proc.new { |file, entity| _parse_file(file, entity) }
69
+ }
70
+
71
+ PARSING.update(
72
+ "double" => PARSING["float"],
73
+ "dateTime" => PARSING["datetime"]
74
+ )
75
+ end
76
+
77
+ attr_reader :backend
78
+ delegate :parse, :to => :backend
79
+
80
+ def backend=(name)
81
+ if name.is_a?(Module)
82
+ @backend = name
83
+ else
84
+ require "active_support/xml_mini/#{name.to_s.downcase}"
85
+ @backend = ActiveSupport.const_get("XmlMini_#{name}")
86
+ end
87
+ end
88
+
89
+ def with_backend(name)
90
+ old_backend, self.backend = backend, name
91
+ yield
92
+ ensure
93
+ self.backend = old_backend
94
+ end
95
+
96
+ def to_tag(key, value, options)
97
+ type_name = options.delete(:type)
98
+ merged_options = options.merge(:root => key, :skip_instruct => true)
99
+
100
+ if value.is_a?(::Method) || value.is_a?(::Proc)
101
+ if value.arity == 1
102
+ value.call(merged_options)
103
+ else
104
+ value.call(merged_options, key.to_s.singularize)
105
+ end
106
+ elsif value.respond_to?(:to_xml)
107
+ value.to_xml(merged_options)
108
+ else
109
+ type_name ||= TYPE_NAMES[value.class.name]
110
+ type_name ||= value.class.name if value && !value.respond_to?(:to_str)
111
+ type_name = type_name.to_s if type_name
112
+
113
+ key = rename_key(key.to_s, options)
114
+
115
+ attributes = options[:skip_types] || type_name.nil? ? { } : { :type => type_name }
116
+ attributes[:nil] = true if value.nil?
117
+
118
+ encoding = options[:encoding] || DEFAULT_ENCODINGS[type_name]
119
+ attributes[:encoding] = encoding if encoding
120
+
121
+ formatted_value = FORMATTING[type_name] && !value.nil? ?
122
+ FORMATTING[type_name].call(value) : value
123
+
124
+ options[:builder].tag!(key, formatted_value, attributes)
125
+ end
126
+ end
127
+
128
+ def rename_key(key, options = {})
129
+ camelize = options.has_key?(:camelize) && options[:camelize]
130
+ dasherize = !options.has_key?(:dasherize) || options[:dasherize]
131
+ key = key.camelize if camelize
132
+ key = key.dasherize if dasherize
133
+ key
134
+ end
135
+
136
+ protected
137
+
138
+ # TODO: Add support for other encodings
139
+ def _parse_binary(bin, entity) #:nodoc:
140
+ case entity['encoding']
141
+ when 'base64'
142
+ ActiveSupport::Base64.decode64(bin)
143
+ else
144
+ bin
145
+ end
146
+ end
147
+
148
+ def _parse_file(file, entity)
149
+ f = StringIO.new(ActiveSupport::Base64.decode64(file))
150
+ f.extend(FileLike)
151
+ f.original_filename = entity['name']
152
+ f.content_type = entity['content_type']
153
+ f
154
+ end
155
+ end
156
+
157
+ XmlMini.backend = 'REXML'
158
+ end
@@ -0,0 +1,168 @@
1
+ raise "JRuby is required to use the JDOM backend for XmlMini" unless RUBY_PLATFORM =~ /java/
2
+
3
+ require 'jruby'
4
+ include Java
5
+
6
+ require 'active_support/core_ext/object/blank'
7
+
8
+ import javax.xml.parsers.DocumentBuilder unless defined? DocumentBuilder
9
+ import javax.xml.parsers.DocumentBuilderFactory unless defined? DocumentBuilderFactory
10
+ import java.io.StringReader unless defined? StringReader
11
+ import org.xml.sax.InputSource unless defined? InputSource
12
+ import org.xml.sax.Attributes unless defined? Attributes
13
+ import org.w3c.dom.Node unless defined? Node
14
+
15
+ # = XmlMini JRuby JDOM implementation
16
+ module ActiveSupport
17
+ module XmlMini_JDOM #:nodoc:
18
+ extend self
19
+
20
+ CONTENT_KEY = '__content__'.freeze
21
+
22
+ NODE_TYPE_NAMES = %w{ATTRIBUTE_NODE CDATA_SECTION_NODE COMMENT_NODE DOCUMENT_FRAGMENT_NODE
23
+ DOCUMENT_NODE DOCUMENT_TYPE_NODE ELEMENT_NODE ENTITY_NODE ENTITY_REFERENCE_NODE NOTATION_NODE
24
+ PROCESSING_INSTRUCTION_NODE TEXT_NODE}
25
+
26
+ node_type_map = {}
27
+ NODE_TYPE_NAMES.each { |type| node_type_map[Node.send(type)] = type }
28
+
29
+ # Parse an XML Document string or IO into a simple hash using Java's jdom.
30
+ # data::
31
+ # XML Document string or IO to parse
32
+ def parse(data)
33
+ if data.respond_to?(:read)
34
+ data = data.read
35
+ end
36
+
37
+ if data.blank?
38
+ {}
39
+ else
40
+ @dbf = DocumentBuilderFactory.new_instance
41
+ xml_string_reader = StringReader.new(data)
42
+ xml_input_source = InputSource.new(xml_string_reader)
43
+ doc = @dbf.new_document_builder.parse(xml_input_source)
44
+ merge_element!({}, doc.document_element)
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ # Convert an XML element and merge into the hash
51
+ #
52
+ # hash::
53
+ # Hash to merge the converted element into.
54
+ # element::
55
+ # XML element to merge into hash
56
+ def merge_element!(hash, element)
57
+ merge!(hash, element.tag_name, collapse(element))
58
+ end
59
+
60
+ # Actually converts an XML document element into a data structure.
61
+ #
62
+ # element::
63
+ # The document element to be collapsed.
64
+ def collapse(element)
65
+ hash = get_attributes(element)
66
+
67
+ child_nodes = element.child_nodes
68
+ if child_nodes.length > 0
69
+ for i in 0...child_nodes.length
70
+ child = child_nodes.item(i)
71
+ merge_element!(hash, child) unless child.node_type == Node.TEXT_NODE
72
+ end
73
+ merge_texts!(hash, element) unless empty_content?(element)
74
+ hash
75
+ else
76
+ merge_texts!(hash, element)
77
+ end
78
+ end
79
+
80
+ # Merge all the texts of an element into the hash
81
+ #
82
+ # hash::
83
+ # Hash to add the converted element to.
84
+ # element::
85
+ # XML element whose texts are to me merged into the hash
86
+ def merge_texts!(hash, element)
87
+ text_children = texts(element)
88
+ if text_children.join.empty?
89
+ hash
90
+ else
91
+ # must use value to prevent double-escaping
92
+ merge!(hash, CONTENT_KEY, text_children.join)
93
+ end
94
+ end
95
+
96
+ # Adds a new key/value pair to an existing Hash. If the key to be added
97
+ # already exists and the existing value associated with key is not
98
+ # an Array, it will be wrapped in an Array. Then the new value is
99
+ # appended to that Array.
100
+ #
101
+ # hash::
102
+ # Hash to add key/value pair to.
103
+ # key::
104
+ # Key to be added.
105
+ # value::
106
+ # Value to be associated with key.
107
+ def merge!(hash, key, value)
108
+ if hash.has_key?(key)
109
+ if hash[key].instance_of?(Array)
110
+ hash[key] << value
111
+ else
112
+ hash[key] = [hash[key], value]
113
+ end
114
+ elsif value.instance_of?(Array)
115
+ hash[key] = [value]
116
+ else
117
+ hash[key] = value
118
+ end
119
+ hash
120
+ end
121
+
122
+ # Converts the attributes array of an XML element into a hash.
123
+ # Returns an empty Hash if node has no attributes.
124
+ #
125
+ # element::
126
+ # XML element to extract attributes from.
127
+ def get_attributes(element)
128
+ attribute_hash = {}
129
+ attributes = element.attributes
130
+ for i in 0...attributes.length
131
+ attribute_hash[attributes.item(i).name] = attributes.item(i).value
132
+ end
133
+ attribute_hash
134
+ end
135
+
136
+ # Determines if a document element has text content
137
+ #
138
+ # element::
139
+ # XML element to be checked.
140
+ def texts(element)
141
+ texts = []
142
+ child_nodes = element.child_nodes
143
+ for i in 0...child_nodes.length
144
+ item = child_nodes.item(i)
145
+ if item.node_type == Node.TEXT_NODE
146
+ texts << item.get_data
147
+ end
148
+ end
149
+ texts
150
+ end
151
+
152
+ # Determines if a document element has text content
153
+ #
154
+ # element::
155
+ # XML element to be checked.
156
+ def empty_content?(element)
157
+ text = ''
158
+ child_nodes = element.child_nodes
159
+ for i in 0...child_nodes.length
160
+ item = child_nodes.item(i)
161
+ if item.node_type == Node.TEXT_NODE
162
+ text << item.get_data.strip
163
+ end
164
+ end
165
+ text.strip.length == 0
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,80 @@
1
+ require 'libxml'
2
+ require 'active_support/core_ext/object/returning'
3
+ require 'active_support/core_ext/object/blank'
4
+
5
+ # = XmlMini LibXML implementation
6
+ module ActiveSupport
7
+ module XmlMini_LibXML #:nodoc:
8
+ extend self
9
+
10
+ # Parse an XML Document string or IO into a simple hash using libxml.
11
+ # data::
12
+ # XML Document string or IO to parse
13
+ def parse(data)
14
+ if !data.respond_to?(:read)
15
+ data = StringIO.new(data || '')
16
+ end
17
+
18
+ char = data.getc
19
+ if char.nil?
20
+ {}
21
+ else
22
+ data.ungetc(char)
23
+ LibXML::XML::Parser.io(data).parse.to_hash
24
+ end
25
+ end
26
+
27
+ end
28
+ end
29
+
30
+ module LibXML #:nodoc:
31
+ module Conversions #:nodoc:
32
+ module Document #:nodoc:
33
+ def to_hash
34
+ root.to_hash
35
+ end
36
+ end
37
+
38
+ module Node #:nodoc:
39
+ CONTENT_ROOT = '__content__'.freeze
40
+
41
+ # Convert XML document to hash
42
+ #
43
+ # hash::
44
+ # Hash to merge the converted element into.
45
+ def to_hash(hash={})
46
+ node_hash = {}
47
+
48
+ # Insert node hash into parent hash correctly.
49
+ case hash[name]
50
+ when Array then hash[name] << node_hash
51
+ when Hash then hash[name] = [hash[name], node_hash]
52
+ when nil then hash[name] = node_hash
53
+ end
54
+
55
+ # Handle child elements
56
+ each_child do |c|
57
+ if c.element?
58
+ c.to_hash(node_hash)
59
+ elsif c.text? || c.cdata?
60
+ node_hash[CONTENT_ROOT] ||= ''
61
+ node_hash[CONTENT_ROOT] << c.content
62
+ end
63
+ end
64
+
65
+ # Remove content node if it is blank
66
+ if node_hash.length > 1 && node_hash[CONTENT_ROOT].blank?
67
+ node_hash.delete(CONTENT_ROOT)
68
+ end
69
+
70
+ # Handle attributes
71
+ each_attr { |a| node_hash[a.name] = a.value }
72
+
73
+ hash
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ LibXML::XML::Document.send(:include, LibXML::Conversions::Document)
80
+ LibXML::XML::Node.send(:include, LibXML::Conversions::Node)
@@ -0,0 +1,85 @@
1
+ require 'libxml'
2
+ require 'active_support/core_ext/object/blank'
3
+
4
+ # = XmlMini LibXML implementation using a SAX-based parser
5
+ module ActiveSupport
6
+ module XmlMini_LibXMLSAX
7
+ extend self
8
+
9
+ # Class that will build the hash while the XML document
10
+ # is being parsed using SAX events.
11
+ class HashBuilder
12
+
13
+ include LibXML::XML::SaxParser::Callbacks
14
+
15
+ CONTENT_KEY = '__content__'.freeze
16
+ HASH_SIZE_KEY = '__hash_size__'.freeze
17
+
18
+ attr_reader :hash
19
+
20
+ def current_hash
21
+ @hash_stack.last
22
+ end
23
+
24
+ def on_start_document
25
+ @hash = { CONTENT_KEY => '' }
26
+ @hash_stack = [@hash]
27
+ end
28
+
29
+ def on_end_document
30
+ @hash = @hash_stack.pop
31
+ @hash.delete(CONTENT_KEY)
32
+ end
33
+
34
+ def on_start_element(name, attrs = {})
35
+ new_hash = { CONTENT_KEY => '' }.merge(attrs)
36
+ new_hash[HASH_SIZE_KEY] = new_hash.size + 1
37
+
38
+ case current_hash[name]
39
+ when Array then current_hash[name] << new_hash
40
+ when Hash then current_hash[name] = [current_hash[name], new_hash]
41
+ when nil then current_hash[name] = new_hash
42
+ end
43
+
44
+ @hash_stack.push(new_hash)
45
+ end
46
+
47
+ def on_end_element(name)
48
+ if current_hash.length > current_hash.delete(HASH_SIZE_KEY) && current_hash[CONTENT_KEY].blank? || current_hash[CONTENT_KEY] == ''
49
+ current_hash.delete(CONTENT_KEY)
50
+ end
51
+ @hash_stack.pop
52
+ end
53
+
54
+ def on_characters(string)
55
+ current_hash[CONTENT_KEY] << string
56
+ end
57
+
58
+ alias_method :on_cdata_block, :on_characters
59
+ end
60
+
61
+ attr_accessor :document_class
62
+ self.document_class = HashBuilder
63
+
64
+ def parse(data)
65
+ if !data.respond_to?(:read)
66
+ data = StringIO.new(data || '')
67
+ end
68
+
69
+ char = data.getc
70
+ if char.nil?
71
+ {}
72
+ else
73
+ data.ungetc(char)
74
+
75
+ LibXML::XML::Error.set_handler(&LibXML::XML::Error::QUIET_HANDLER)
76
+ parser = LibXML::XML::SaxParser.io(data)
77
+ document = self.document_class.new
78
+
79
+ parser.callbacks = document
80
+ parser.parse
81
+ document.hash
82
+ end
83
+ end
84
+ end
85
+ end