activesupport 5.0.7.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (236) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1018 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +39 -0
  5. data/lib/active_support.rb +99 -0
  6. data/lib/active_support/all.rb +3 -0
  7. data/lib/active_support/array_inquirer.rb +44 -0
  8. data/lib/active_support/backtrace_cleaner.rb +103 -0
  9. data/lib/active_support/benchmarkable.rb +49 -0
  10. data/lib/active_support/builder.rb +6 -0
  11. data/lib/active_support/cache.rb +701 -0
  12. data/lib/active_support/cache/file_store.rb +204 -0
  13. data/lib/active_support/cache/mem_cache_store.rb +207 -0
  14. data/lib/active_support/cache/memory_store.rb +167 -0
  15. data/lib/active_support/cache/null_store.rb +41 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +172 -0
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +44 -0
  18. data/lib/active_support/callbacks.rb +791 -0
  19. data/lib/active_support/concern.rb +142 -0
  20. data/lib/active_support/concurrency/latch.rb +26 -0
  21. data/lib/active_support/concurrency/share_lock.rb +226 -0
  22. data/lib/active_support/configurable.rb +148 -0
  23. data/lib/active_support/core_ext.rb +4 -0
  24. data/lib/active_support/core_ext/array.rb +7 -0
  25. data/lib/active_support/core_ext/array/access.rb +90 -0
  26. data/lib/active_support/core_ext/array/conversions.rb +211 -0
  27. data/lib/active_support/core_ext/array/extract_options.rb +29 -0
  28. data/lib/active_support/core_ext/array/grouping.rb +107 -0
  29. data/lib/active_support/core_ext/array/inquiry.rb +17 -0
  30. data/lib/active_support/core_ext/array/prepend_and_append.rb +7 -0
  31. data/lib/active_support/core_ext/array/wrap.rb +46 -0
  32. data/lib/active_support/core_ext/benchmark.rb +14 -0
  33. data/lib/active_support/core_ext/big_decimal.rb +1 -0
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +14 -0
  35. data/lib/active_support/core_ext/class.rb +2 -0
  36. data/lib/active_support/core_ext/class/attribute.rb +128 -0
  37. data/lib/active_support/core_ext/class/attribute_accessors.rb +4 -0
  38. data/lib/active_support/core_ext/class/subclasses.rb +41 -0
  39. data/lib/active_support/core_ext/date.rb +5 -0
  40. data/lib/active_support/core_ext/date/acts_like.rb +8 -0
  41. data/lib/active_support/core_ext/date/blank.rb +12 -0
  42. data/lib/active_support/core_ext/date/calculations.rb +143 -0
  43. data/lib/active_support/core_ext/date/conversions.rb +95 -0
  44. data/lib/active_support/core_ext/date/zones.rb +6 -0
  45. data/lib/active_support/core_ext/date_and_time/calculations.rb +335 -0
  46. data/lib/active_support/core_ext/date_and_time/compatibility.rb +14 -0
  47. data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
  48. data/lib/active_support/core_ext/date_time.rb +5 -0
  49. data/lib/active_support/core_ext/date_time/acts_like.rb +14 -0
  50. data/lib/active_support/core_ext/date_time/blank.rb +12 -0
  51. data/lib/active_support/core_ext/date_time/calculations.rb +199 -0
  52. data/lib/active_support/core_ext/date_time/compatibility.rb +16 -0
  53. data/lib/active_support/core_ext/date_time/conversions.rb +105 -0
  54. data/lib/active_support/core_ext/digest/uuid.rb +51 -0
  55. data/lib/active_support/core_ext/enumerable.rb +146 -0
  56. data/lib/active_support/core_ext/file.rb +1 -0
  57. data/lib/active_support/core_ext/file/atomic.rb +68 -0
  58. data/lib/active_support/core_ext/hash.rb +9 -0
  59. data/lib/active_support/core_ext/hash/compact.rb +24 -0
  60. data/lib/active_support/core_ext/hash/conversions.rb +262 -0
  61. data/lib/active_support/core_ext/hash/deep_merge.rb +38 -0
  62. data/lib/active_support/core_ext/hash/except.rb +22 -0
  63. data/lib/active_support/core_ext/hash/indifferent_access.rb +23 -0
  64. data/lib/active_support/core_ext/hash/keys.rb +170 -0
  65. data/lib/active_support/core_ext/hash/reverse_merge.rb +22 -0
  66. data/lib/active_support/core_ext/hash/slice.rb +48 -0
  67. data/lib/active_support/core_ext/hash/transform_values.rb +29 -0
  68. data/lib/active_support/core_ext/integer.rb +3 -0
  69. data/lib/active_support/core_ext/integer/inflections.rb +29 -0
  70. data/lib/active_support/core_ext/integer/multiple.rb +10 -0
  71. data/lib/active_support/core_ext/integer/time.rb +29 -0
  72. data/lib/active_support/core_ext/kernel.rb +4 -0
  73. data/lib/active_support/core_ext/kernel/agnostics.rb +11 -0
  74. data/lib/active_support/core_ext/kernel/concern.rb +12 -0
  75. data/lib/active_support/core_ext/kernel/debugger.rb +3 -0
  76. data/lib/active_support/core_ext/kernel/reporting.rb +43 -0
  77. data/lib/active_support/core_ext/kernel/singleton_class.rb +6 -0
  78. data/lib/active_support/core_ext/load_error.rb +31 -0
  79. data/lib/active_support/core_ext/marshal.rb +22 -0
  80. data/lib/active_support/core_ext/module.rb +12 -0
  81. data/lib/active_support/core_ext/module/aliasing.rb +74 -0
  82. data/lib/active_support/core_ext/module/anonymous.rb +28 -0
  83. data/lib/active_support/core_ext/module/attr_internal.rb +36 -0
  84. data/lib/active_support/core_ext/module/attribute_accessors.rb +212 -0
  85. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +141 -0
  86. data/lib/active_support/core_ext/module/concerning.rb +135 -0
  87. data/lib/active_support/core_ext/module/delegation.rb +216 -0
  88. data/lib/active_support/core_ext/module/deprecation.rb +23 -0
  89. data/lib/active_support/core_ext/module/introspection.rb +68 -0
  90. data/lib/active_support/core_ext/module/method_transplanting.rb +3 -0
  91. data/lib/active_support/core_ext/module/qualified_const.rb +70 -0
  92. data/lib/active_support/core_ext/module/reachable.rb +8 -0
  93. data/lib/active_support/core_ext/module/remove_method.rb +35 -0
  94. data/lib/active_support/core_ext/name_error.rb +31 -0
  95. data/lib/active_support/core_ext/numeric.rb +4 -0
  96. data/lib/active_support/core_ext/numeric/bytes.rb +64 -0
  97. data/lib/active_support/core_ext/numeric/conversions.rb +144 -0
  98. data/lib/active_support/core_ext/numeric/inquiry.rb +26 -0
  99. data/lib/active_support/core_ext/numeric/time.rb +74 -0
  100. data/lib/active_support/core_ext/object.rb +14 -0
  101. data/lib/active_support/core_ext/object/acts_like.rb +10 -0
  102. data/lib/active_support/core_ext/object/blank.rb +143 -0
  103. data/lib/active_support/core_ext/object/conversions.rb +4 -0
  104. data/lib/active_support/core_ext/object/deep_dup.rb +53 -0
  105. data/lib/active_support/core_ext/object/duplicable.rb +124 -0
  106. data/lib/active_support/core_ext/object/inclusion.rb +27 -0
  107. data/lib/active_support/core_ext/object/instance_variables.rb +28 -0
  108. data/lib/active_support/core_ext/object/json.rb +205 -0
  109. data/lib/active_support/core_ext/object/to_param.rb +1 -0
  110. data/lib/active_support/core_ext/object/to_query.rb +84 -0
  111. data/lib/active_support/core_ext/object/try.rb +146 -0
  112. data/lib/active_support/core_ext/object/with_options.rb +69 -0
  113. data/lib/active_support/core_ext/range.rb +4 -0
  114. data/lib/active_support/core_ext/range/conversions.rb +31 -0
  115. data/lib/active_support/core_ext/range/each.rb +21 -0
  116. data/lib/active_support/core_ext/range/include_range.rb +23 -0
  117. data/lib/active_support/core_ext/range/overlaps.rb +8 -0
  118. data/lib/active_support/core_ext/regexp.rb +5 -0
  119. data/lib/active_support/core_ext/securerandom.rb +23 -0
  120. data/lib/active_support/core_ext/string.rb +13 -0
  121. data/lib/active_support/core_ext/string/access.rb +104 -0
  122. data/lib/active_support/core_ext/string/behavior.rb +6 -0
  123. data/lib/active_support/core_ext/string/conversions.rb +57 -0
  124. data/lib/active_support/core_ext/string/exclude.rb +11 -0
  125. data/lib/active_support/core_ext/string/filters.rb +102 -0
  126. data/lib/active_support/core_ext/string/indent.rb +43 -0
  127. data/lib/active_support/core_ext/string/inflections.rb +244 -0
  128. data/lib/active_support/core_ext/string/inquiry.rb +13 -0
  129. data/lib/active_support/core_ext/string/multibyte.rb +53 -0
  130. data/lib/active_support/core_ext/string/output_safety.rb +260 -0
  131. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -0
  132. data/lib/active_support/core_ext/string/strip.rb +23 -0
  133. data/lib/active_support/core_ext/string/zones.rb +14 -0
  134. data/lib/active_support/core_ext/struct.rb +3 -0
  135. data/lib/active_support/core_ext/time.rb +5 -0
  136. data/lib/active_support/core_ext/time/acts_like.rb +8 -0
  137. data/lib/active_support/core_ext/time/calculations.rb +290 -0
  138. data/lib/active_support/core_ext/time/compatibility.rb +14 -0
  139. data/lib/active_support/core_ext/time/conversions.rb +67 -0
  140. data/lib/active_support/core_ext/time/marshal.rb +3 -0
  141. data/lib/active_support/core_ext/time/zones.rb +111 -0
  142. data/lib/active_support/core_ext/uri.rb +24 -0
  143. data/lib/active_support/dependencies.rb +755 -0
  144. data/lib/active_support/dependencies/autoload.rb +77 -0
  145. data/lib/active_support/dependencies/interlock.rb +55 -0
  146. data/lib/active_support/deprecation.rb +43 -0
  147. data/lib/active_support/deprecation/behaviors.rb +90 -0
  148. data/lib/active_support/deprecation/instance_delegator.rb +37 -0
  149. data/lib/active_support/deprecation/method_wrappers.rb +70 -0
  150. data/lib/active_support/deprecation/proxy_wrappers.rb +149 -0
  151. data/lib/active_support/deprecation/reporting.rb +112 -0
  152. data/lib/active_support/descendants_tracker.rb +60 -0
  153. data/lib/active_support/duration.rb +235 -0
  154. data/lib/active_support/duration/iso8601_parser.rb +122 -0
  155. data/lib/active_support/duration/iso8601_serializer.rb +51 -0
  156. data/lib/active_support/evented_file_update_checker.rb +199 -0
  157. data/lib/active_support/execution_wrapper.rb +126 -0
  158. data/lib/active_support/executor.rb +6 -0
  159. data/lib/active_support/file_update_checker.rb +157 -0
  160. data/lib/active_support/gem_version.rb +15 -0
  161. data/lib/active_support/gzip.rb +36 -0
  162. data/lib/active_support/hash_with_indifferent_access.rb +329 -0
  163. data/lib/active_support/i18n.rb +13 -0
  164. data/lib/active_support/i18n_railtie.rb +115 -0
  165. data/lib/active_support/inflections.rb +70 -0
  166. data/lib/active_support/inflector.rb +7 -0
  167. data/lib/active_support/inflector/inflections.rb +242 -0
  168. data/lib/active_support/inflector/methods.rb +390 -0
  169. data/lib/active_support/inflector/transliterate.rb +112 -0
  170. data/lib/active_support/json.rb +2 -0
  171. data/lib/active_support/json/decoding.rb +74 -0
  172. data/lib/active_support/json/encoding.rb +127 -0
  173. data/lib/active_support/key_generator.rb +71 -0
  174. data/lib/active_support/lazy_load_hooks.rb +76 -0
  175. data/lib/active_support/locale/en.yml +135 -0
  176. data/lib/active_support/log_subscriber.rb +109 -0
  177. data/lib/active_support/log_subscriber/test_helper.rb +104 -0
  178. data/lib/active_support/logger.rb +106 -0
  179. data/lib/active_support/logger_silence.rb +28 -0
  180. data/lib/active_support/logger_thread_safe_level.rb +31 -0
  181. data/lib/active_support/message_encryptor.rb +114 -0
  182. data/lib/active_support/message_verifier.rb +134 -0
  183. data/lib/active_support/multibyte.rb +21 -0
  184. data/lib/active_support/multibyte/chars.rb +231 -0
  185. data/lib/active_support/multibyte/unicode.rb +413 -0
  186. data/lib/active_support/notifications.rb +212 -0
  187. data/lib/active_support/notifications/fanout.rb +157 -0
  188. data/lib/active_support/notifications/instrumenter.rb +91 -0
  189. data/lib/active_support/number_helper.rb +368 -0
  190. data/lib/active_support/number_helper/number_converter.rb +182 -0
  191. data/lib/active_support/number_helper/number_to_currency_converter.rb +44 -0
  192. data/lib/active_support/number_helper/number_to_delimited_converter.rb +28 -0
  193. data/lib/active_support/number_helper/number_to_human_converter.rb +68 -0
  194. data/lib/active_support/number_helper/number_to_human_size_converter.rb +62 -0
  195. data/lib/active_support/number_helper/number_to_percentage_converter.rb +12 -0
  196. data/lib/active_support/number_helper/number_to_phone_converter.rb +58 -0
  197. data/lib/active_support/number_helper/number_to_rounded_converter.rb +92 -0
  198. data/lib/active_support/option_merger.rb +25 -0
  199. data/lib/active_support/ordered_hash.rb +48 -0
  200. data/lib/active_support/ordered_options.rb +81 -0
  201. data/lib/active_support/per_thread_registry.rb +58 -0
  202. data/lib/active_support/proxy_object.rb +13 -0
  203. data/lib/active_support/rails.rb +27 -0
  204. data/lib/active_support/railtie.rb +51 -0
  205. data/lib/active_support/reloader.rb +129 -0
  206. data/lib/active_support/rescuable.rb +173 -0
  207. data/lib/active_support/security_utils.rb +27 -0
  208. data/lib/active_support/string_inquirer.rb +26 -0
  209. data/lib/active_support/subscriber.rb +120 -0
  210. data/lib/active_support/tagged_logging.rb +77 -0
  211. data/lib/active_support/test_case.rb +88 -0
  212. data/lib/active_support/testing/assertions.rb +99 -0
  213. data/lib/active_support/testing/autorun.rb +5 -0
  214. data/lib/active_support/testing/constant_lookup.rb +50 -0
  215. data/lib/active_support/testing/declarative.rb +26 -0
  216. data/lib/active_support/testing/deprecation.rb +36 -0
  217. data/lib/active_support/testing/file_fixtures.rb +34 -0
  218. data/lib/active_support/testing/isolation.rb +115 -0
  219. data/lib/active_support/testing/method_call_assertions.rb +41 -0
  220. data/lib/active_support/testing/setup_and_teardown.rb +50 -0
  221. data/lib/active_support/testing/stream.rb +42 -0
  222. data/lib/active_support/testing/tagged_logging.rb +25 -0
  223. data/lib/active_support/testing/time_helpers.rb +136 -0
  224. data/lib/active_support/time.rb +18 -0
  225. data/lib/active_support/time_with_zone.rb +511 -0
  226. data/lib/active_support/values/time_zone.rb +484 -0
  227. data/lib/active_support/values/unicode_tables.dat +0 -0
  228. data/lib/active_support/version.rb +8 -0
  229. data/lib/active_support/xml_mini.rb +209 -0
  230. data/lib/active_support/xml_mini/jdom.rb +181 -0
  231. data/lib/active_support/xml_mini/libxml.rb +77 -0
  232. data/lib/active_support/xml_mini/libxmlsax.rb +82 -0
  233. data/lib/active_support/xml_mini/nokogiri.rb +81 -0
  234. data/lib/active_support/xml_mini/nokogirisax.rb +85 -0
  235. data/lib/active_support/xml_mini/rexml.rb +128 -0
  236. metadata +349 -0
@@ -0,0 +1,8 @@
1
+ require_relative 'gem_version'
2
+
3
+ module ActiveSupport
4
+ # Returns the version of the currently loaded ActiveSupport as a <tt>Gem::Version</tt>
5
+ def self.version
6
+ gem_version
7
+ end
8
+ end
@@ -0,0 +1,209 @@
1
+ require 'time'
2
+ require 'base64'
3
+ require 'bigdecimal'
4
+ require 'active_support/core_ext/module/delegation'
5
+ require 'active_support/core_ext/string/inflections'
6
+ require 'active_support/core_ext/date_time/calculations'
7
+
8
+ module ActiveSupport
9
+ # = XmlMini
10
+ #
11
+ # To use the much faster libxml parser:
12
+ # gem 'libxml-ruby', '=0.9.7'
13
+ # XmlMini.backend = 'LibXML'
14
+ module XmlMini
15
+ extend self
16
+
17
+ # This module decorates files deserialized using Hash.from_xml with
18
+ # the <tt>original_filename</tt> and <tt>content_type</tt> methods.
19
+ module FileLike #:nodoc:
20
+ attr_writer :original_filename, :content_type
21
+
22
+ def original_filename
23
+ @original_filename || 'untitled'
24
+ end
25
+
26
+ def content_type
27
+ @content_type || 'application/octet-stream'
28
+ end
29
+ end
30
+
31
+ DEFAULT_ENCODINGS = {
32
+ "binary" => "base64"
33
+ } unless defined?(DEFAULT_ENCODINGS)
34
+
35
+ unless defined?(TYPE_NAMES)
36
+ TYPE_NAMES = {
37
+ "Symbol" => "symbol",
38
+ "Integer" => "integer",
39
+ "BigDecimal" => "decimal",
40
+ "Float" => "float",
41
+ "TrueClass" => "boolean",
42
+ "FalseClass" => "boolean",
43
+ "Date" => "date",
44
+ "DateTime" => "dateTime",
45
+ "Time" => "dateTime",
46
+ "Array" => "array",
47
+ "Hash" => "hash"
48
+ }
49
+
50
+ # No need to map these on Ruby 2.4+
51
+ TYPE_NAMES["Fixnum"] = "integer" unless 0.class == Integer
52
+ TYPE_NAMES["Bignum"] = "integer" unless 0.class == Integer
53
+ end
54
+
55
+ FORMATTING = {
56
+ "symbol" => Proc.new { |symbol| symbol.to_s },
57
+ "date" => Proc.new { |date| date.to_s(:db) },
58
+ "dateTime" => Proc.new { |time| time.xmlschema },
59
+ "binary" => Proc.new { |binary| ::Base64.encode64(binary) },
60
+ "yaml" => Proc.new { |yaml| yaml.to_yaml }
61
+ } unless defined?(FORMATTING)
62
+
63
+ # TODO use regexp instead of Date.parse
64
+ unless defined?(PARSING)
65
+ PARSING = {
66
+ "symbol" => Proc.new { |symbol| symbol.to_s.to_sym },
67
+ "date" => Proc.new { |date| ::Date.parse(date) },
68
+ "datetime" => Proc.new { |time| Time.xmlschema(time).utc rescue ::DateTime.parse(time).utc },
69
+ "integer" => Proc.new { |integer| integer.to_i },
70
+ "float" => Proc.new { |float| float.to_f },
71
+ "decimal" => Proc.new do |number|
72
+ if String === number
73
+ begin
74
+ BigDecimal(number)
75
+ rescue ArgumentError
76
+ BigDecimal('0')
77
+ end
78
+ else
79
+ BigDecimal(number)
80
+ end
81
+ end,
82
+ "boolean" => Proc.new { |boolean| %w(1 true).include?(boolean.to_s.strip) },
83
+ "string" => Proc.new { |string| string.to_s },
84
+ "yaml" => Proc.new { |yaml| YAML::load(yaml) rescue yaml },
85
+ "base64Binary" => Proc.new { |bin| ::Base64.decode64(bin) },
86
+ "binary" => Proc.new { |bin, entity| _parse_binary(bin, entity) },
87
+ "file" => Proc.new { |file, entity| _parse_file(file, entity) }
88
+ }
89
+
90
+ PARSING.update(
91
+ "double" => PARSING["float"],
92
+ "dateTime" => PARSING["datetime"]
93
+ )
94
+ end
95
+
96
+ attr_accessor :depth
97
+ self.depth = 100
98
+
99
+ delegate :parse, :to => :backend
100
+
101
+ def backend
102
+ current_thread_backend || @backend
103
+ end
104
+
105
+ def backend=(name)
106
+ backend = name && cast_backend_name_to_module(name)
107
+ self.current_thread_backend = backend if current_thread_backend
108
+ @backend = backend
109
+ end
110
+
111
+ def with_backend(name)
112
+ old_backend = current_thread_backend
113
+ self.current_thread_backend = name && cast_backend_name_to_module(name)
114
+ yield
115
+ ensure
116
+ self.current_thread_backend = old_backend
117
+ end
118
+
119
+ def to_tag(key, value, options)
120
+ type_name = options.delete(:type)
121
+ merged_options = options.merge(:root => key, :skip_instruct => true)
122
+
123
+ if value.is_a?(::Method) || value.is_a?(::Proc)
124
+ if value.arity == 1
125
+ value.call(merged_options)
126
+ else
127
+ value.call(merged_options, key.to_s.singularize)
128
+ end
129
+ elsif value.respond_to?(:to_xml)
130
+ value.to_xml(merged_options)
131
+ else
132
+ type_name ||= TYPE_NAMES[value.class.name]
133
+ type_name ||= value.class.name if value && !value.respond_to?(:to_str)
134
+ type_name = type_name.to_s if type_name
135
+ type_name = "dateTime" if type_name == "datetime"
136
+
137
+ key = rename_key(key.to_s, options)
138
+
139
+ attributes = options[:skip_types] || type_name.nil? ? { } : { :type => type_name }
140
+ attributes[:nil] = true if value.nil?
141
+
142
+ encoding = options[:encoding] || DEFAULT_ENCODINGS[type_name]
143
+ attributes[:encoding] = encoding if encoding
144
+
145
+ formatted_value = FORMATTING[type_name] && !value.nil? ?
146
+ FORMATTING[type_name].call(value) : value
147
+
148
+ options[:builder].tag!(key, formatted_value, attributes)
149
+ end
150
+ end
151
+
152
+ def rename_key(key, options = {})
153
+ camelize = options[:camelize]
154
+ dasherize = !options.has_key?(:dasherize) || options[:dasherize]
155
+ if camelize
156
+ key = true == camelize ? key.camelize : key.camelize(camelize)
157
+ end
158
+ key = _dasherize(key) if dasherize
159
+ key
160
+ end
161
+
162
+ protected
163
+
164
+ def _dasherize(key)
165
+ # $2 must be a non-greedy regex for this to work
166
+ left, middle, right = /\A(_*)(.*?)(_*)\Z/.match(key.strip)[1,3]
167
+ "#{left}#{middle.tr('_ ', '--')}#{right}"
168
+ end
169
+
170
+ # TODO: Add support for other encodings
171
+ def _parse_binary(bin, entity) #:nodoc:
172
+ case entity['encoding']
173
+ when 'base64'
174
+ ::Base64.decode64(bin)
175
+ else
176
+ bin
177
+ end
178
+ end
179
+
180
+ def _parse_file(file, entity)
181
+ f = StringIO.new(::Base64.decode64(file))
182
+ f.extend(FileLike)
183
+ f.original_filename = entity['name']
184
+ f.content_type = entity['content_type']
185
+ f
186
+ end
187
+
188
+ private
189
+
190
+ def current_thread_backend
191
+ Thread.current[:xml_mini_backend]
192
+ end
193
+
194
+ def current_thread_backend=(name)
195
+ Thread.current[:xml_mini_backend] = name && cast_backend_name_to_module(name)
196
+ end
197
+
198
+ def cast_backend_name_to_module(name)
199
+ if name.is_a?(Module)
200
+ name
201
+ else
202
+ require "active_support/xml_mini/#{name.downcase}"
203
+ ActiveSupport.const_get("XmlMini_#{name}")
204
+ end
205
+ end
206
+ end
207
+
208
+ XmlMini.backend = 'REXML'
209
+ end
@@ -0,0 +1,181 @@
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
+ java_import javax.xml.parsers.DocumentBuilder unless defined? DocumentBuilder
9
+ java_import javax.xml.parsers.DocumentBuilderFactory unless defined? DocumentBuilderFactory
10
+ java_import java.io.StringReader unless defined? StringReader
11
+ java_import org.xml.sax.InputSource unless defined? InputSource
12
+ java_import org.xml.sax.Attributes unless defined? Attributes
13
+ java_import org.w3c.dom.Node unless defined? Node
14
+
15
+ module ActiveSupport
16
+ module XmlMini_JDOM #:nodoc:
17
+ extend self
18
+
19
+ CONTENT_KEY = '__content__'.freeze
20
+
21
+ NODE_TYPE_NAMES = %w{ATTRIBUTE_NODE CDATA_SECTION_NODE COMMENT_NODE DOCUMENT_FRAGMENT_NODE
22
+ DOCUMENT_NODE DOCUMENT_TYPE_NODE ELEMENT_NODE ENTITY_NODE ENTITY_REFERENCE_NODE NOTATION_NODE
23
+ PROCESSING_INSTRUCTION_NODE TEXT_NODE}
24
+
25
+ node_type_map = {}
26
+ NODE_TYPE_NAMES.each { |type| node_type_map[Node.send(type)] = type }
27
+
28
+ # Parse an XML Document string or IO into a simple hash using Java's jdom.
29
+ # data::
30
+ # XML Document string or IO to parse
31
+ def parse(data)
32
+ if data.respond_to?(:read)
33
+ data = data.read
34
+ end
35
+
36
+ if data.blank?
37
+ {}
38
+ else
39
+ @dbf = DocumentBuilderFactory.new_instance
40
+ # secure processing of java xml
41
+ # http://www.ibm.com/developerworks/xml/library/x-tipcfsx/index.html
42
+ @dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false)
43
+ @dbf.setFeature("http://xml.org/sax/features/external-general-entities", false)
44
+ @dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false)
45
+ @dbf.setFeature(javax.xml.XMLConstants::FEATURE_SECURE_PROCESSING, true)
46
+ xml_string_reader = StringReader.new(data)
47
+ xml_input_source = InputSource.new(xml_string_reader)
48
+ doc = @dbf.new_document_builder.parse(xml_input_source)
49
+ merge_element!({CONTENT_KEY => ''}, doc.document_element, XmlMini.depth)
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ # Convert an XML element and merge into the hash
56
+ #
57
+ # hash::
58
+ # Hash to merge the converted element into.
59
+ # element::
60
+ # XML element to merge into hash
61
+ def merge_element!(hash, element, depth)
62
+ raise 'Document too deep!' if depth == 0
63
+ delete_empty(hash)
64
+ merge!(hash, element.tag_name, collapse(element, depth))
65
+ end
66
+
67
+ def delete_empty(hash)
68
+ hash.delete(CONTENT_KEY) if hash[CONTENT_KEY] == ''
69
+ end
70
+
71
+ # Actually converts an XML document element into a data structure.
72
+ #
73
+ # element::
74
+ # The document element to be collapsed.
75
+ def collapse(element, depth)
76
+ hash = get_attributes(element)
77
+
78
+ child_nodes = element.child_nodes
79
+ if child_nodes.length > 0
80
+ (0...child_nodes.length).each do |i|
81
+ child = child_nodes.item(i)
82
+ merge_element!(hash, child, depth - 1) unless child.node_type == Node.TEXT_NODE
83
+ end
84
+ merge_texts!(hash, element) unless empty_content?(element)
85
+ hash
86
+ else
87
+ merge_texts!(hash, element)
88
+ end
89
+ end
90
+
91
+ # Merge all the texts of an element into the hash
92
+ #
93
+ # hash::
94
+ # Hash to add the converted element to.
95
+ # element::
96
+ # XML element whose texts are to me merged into the hash
97
+ def merge_texts!(hash, element)
98
+ delete_empty(hash)
99
+ text_children = texts(element)
100
+ if text_children.join.empty?
101
+ hash
102
+ else
103
+ # must use value to prevent double-escaping
104
+ merge!(hash, CONTENT_KEY, text_children.join)
105
+ end
106
+ end
107
+
108
+ # Adds a new key/value pair to an existing Hash. If the key to be added
109
+ # already exists and the existing value associated with key is not
110
+ # an Array, it will be wrapped in an Array. Then the new value is
111
+ # appended to that Array.
112
+ #
113
+ # hash::
114
+ # Hash to add key/value pair to.
115
+ # key::
116
+ # Key to be added.
117
+ # value::
118
+ # Value to be associated with key.
119
+ def merge!(hash, key, value)
120
+ if hash.has_key?(key)
121
+ if hash[key].instance_of?(Array)
122
+ hash[key] << value
123
+ else
124
+ hash[key] = [hash[key], value]
125
+ end
126
+ elsif value.instance_of?(Array)
127
+ hash[key] = [value]
128
+ else
129
+ hash[key] = value
130
+ end
131
+ hash
132
+ end
133
+
134
+ # Converts the attributes array of an XML element into a hash.
135
+ # Returns an empty Hash if node has no attributes.
136
+ #
137
+ # element::
138
+ # XML element to extract attributes from.
139
+ def get_attributes(element)
140
+ attribute_hash = {}
141
+ attributes = element.attributes
142
+ (0...attributes.length).each do |i|
143
+ attribute_hash[CONTENT_KEY] ||= ''
144
+ attribute_hash[attributes.item(i).name] = attributes.item(i).value
145
+ end
146
+ attribute_hash
147
+ end
148
+
149
+ # Determines if a document element has text content
150
+ #
151
+ # element::
152
+ # XML element to be checked.
153
+ def texts(element)
154
+ texts = []
155
+ child_nodes = element.child_nodes
156
+ (0...child_nodes.length).each do |i|
157
+ item = child_nodes.item(i)
158
+ if item.node_type == Node.TEXT_NODE
159
+ texts << item.get_data
160
+ end
161
+ end
162
+ texts
163
+ end
164
+
165
+ # Determines if a document element has text content
166
+ #
167
+ # element::
168
+ # XML element to be checked.
169
+ def empty_content?(element)
170
+ text = ''
171
+ child_nodes = element.child_nodes
172
+ (0...child_nodes.length).each do |i|
173
+ item = child_nodes.item(i)
174
+ if item.node_type == Node.TEXT_NODE
175
+ text << item.get_data.strip
176
+ end
177
+ end
178
+ text.strip.length == 0
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,77 @@
1
+ require 'libxml'
2
+ require 'active_support/core_ext/object/blank'
3
+ require 'stringio'
4
+
5
+ module ActiveSupport
6
+ module XmlMini_LibXML #:nodoc:
7
+ extend self
8
+
9
+ # Parse an XML Document string or IO into a simple hash using libxml.
10
+ # data::
11
+ # XML Document string or IO to parse
12
+ def parse(data)
13
+ if !data.respond_to?(:read)
14
+ data = StringIO.new(data || '')
15
+ end
16
+
17
+ if data.eof?
18
+ {}
19
+ else
20
+ LibXML::XML::Parser.io(data).parse.to_hash
21
+ end
22
+ end
23
+
24
+ end
25
+ end
26
+
27
+ module LibXML #:nodoc:
28
+ module Conversions #:nodoc:
29
+ module Document #:nodoc:
30
+ def to_hash
31
+ root.to_hash
32
+ end
33
+ end
34
+
35
+ module Node #:nodoc:
36
+ CONTENT_ROOT = '__content__'.freeze
37
+
38
+ # Convert XML document to hash.
39
+ #
40
+ # hash::
41
+ # Hash to merge the converted element into.
42
+ def to_hash(hash={})
43
+ node_hash = {}
44
+
45
+ # Insert node hash into parent hash correctly.
46
+ case hash[name]
47
+ when Array then hash[name] << node_hash
48
+ when Hash then hash[name] = [hash[name], node_hash]
49
+ when nil then hash[name] = node_hash
50
+ end
51
+
52
+ # Handle child elements
53
+ each_child do |c|
54
+ if c.element?
55
+ c.to_hash(node_hash)
56
+ elsif c.text? || c.cdata?
57
+ node_hash[CONTENT_ROOT] ||= ''
58
+ node_hash[CONTENT_ROOT] << c.content
59
+ end
60
+ end
61
+
62
+ # Remove content node if it is blank
63
+ if node_hash.length > 1 && node_hash[CONTENT_ROOT].blank?
64
+ node_hash.delete(CONTENT_ROOT)
65
+ end
66
+
67
+ # Handle attributes
68
+ each_attr { |a| node_hash[a.name] = a.value }
69
+
70
+ hash
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ LibXML::XML::Document.include(LibXML::Conversions::Document)
77
+ LibXML::XML::Node.include(LibXML::Conversions::Node)