oca 3.0.1
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.
- data/lib/OpenNebula/Acl.rb +266 -0
- data/lib/OpenNebula/AclPool.rb +52 -0
- data/lib/OpenNebula/Group.rb +148 -0
- data/lib/OpenNebula/GroupPool.rb +52 -0
- data/lib/OpenNebula/Host.rb +142 -0
- data/lib/OpenNebula/HostPool.rb +52 -0
- data/lib/OpenNebula/Image.rb +214 -0
- data/lib/OpenNebula/ImagePool.rb +72 -0
- data/lib/OpenNebula/Pool.rb +245 -0
- data/lib/OpenNebula/Template.rb +146 -0
- data/lib/OpenNebula/TemplatePool.rb +71 -0
- data/lib/OpenNebula/User.rb +117 -0
- data/lib/OpenNebula/UserPool.rb +52 -0
- data/lib/OpenNebula/VirtualMachine.rb +289 -0
- data/lib/OpenNebula/VirtualMachinePool.rb +117 -0
- data/lib/OpenNebula/VirtualNetwork.rb +166 -0
- data/lib/OpenNebula/VirtualNetworkPool.rb +72 -0
- data/lib/OpenNebula/XMLUtils.rb +340 -0
- data/lib/OpenNebula.rb +144 -0
- data/lib/oca.rb +1 -0
- data/test/HostPool_spec.rb +82 -0
- data/test/Host_spec.rb +220 -0
- data/test/UserPool_spec.rb +66 -0
- data/test/User_spec.rb +146 -0
- data/test/VirtualMachinePool_spec.rb +118 -0
- data/test/VirtualMachine_spec.rb +473 -0
- data/test/VirtualNetworkPool_spec.rb +88 -0
- data/test/VirtualNetwork_spec.rb +156 -0
- data/test/fixtures/host.xml +38 -0
- data/test/fixtures/hostpool.xml +52 -0
- data/test/fixtures/user.xml +6 -0
- data/test/fixtures/userpool.xml +14 -0
- data/test/fixtures/vm.xml +59 -0
- data/test/fixtures/vmpool.xml +92 -0
- data/test/fixtures/vnet.xml +23 -0
- data/test/fixtures/vnetpool.xml +20 -0
- data/test/helpers/MockClient.rb +49 -0
- metadata +131 -0
@@ -0,0 +1,117 @@
|
|
1
|
+
# -------------------------------------------------------------------------- #
|
2
|
+
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
|
3
|
+
# #
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
5
|
+
# not use this file except in compliance with the License. You may obtain #
|
6
|
+
# a copy of the License at #
|
7
|
+
# #
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0 #
|
9
|
+
# #
|
10
|
+
# Unless required by applicable law or agreed to in writing, software #
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS, #
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
13
|
+
# See the License for the specific language governing permissions and #
|
14
|
+
# limitations under the License. #
|
15
|
+
#--------------------------------------------------------------------------- #
|
16
|
+
|
17
|
+
require 'OpenNebula/Pool'
|
18
|
+
|
19
|
+
module OpenNebula
|
20
|
+
class VirtualMachinePool < Pool
|
21
|
+
#######################################################################
|
22
|
+
# Constants and Class attribute accessors
|
23
|
+
#######################################################################
|
24
|
+
|
25
|
+
VM_POOL_METHODS = {
|
26
|
+
:info => "vmpool.info"
|
27
|
+
}
|
28
|
+
|
29
|
+
# Constants for info queries (include/RequestManagerPoolInfoFilter.h)
|
30
|
+
INFO_NOT_DONE = -1
|
31
|
+
INFO_ALL_VM = -2
|
32
|
+
|
33
|
+
#######################################################################
|
34
|
+
# Class constructor & Pool Methods
|
35
|
+
#######################################################################
|
36
|
+
|
37
|
+
# +client+ a Client object that represents a XML-RPC connection
|
38
|
+
# +user_id+ is to refer to a Pool with VirtualMachines from that user
|
39
|
+
def initialize(client, user_id=0)
|
40
|
+
super('VM_POOL','VM',client)
|
41
|
+
|
42
|
+
@user_id = user_id
|
43
|
+
end
|
44
|
+
|
45
|
+
# Default Factory Method for the Pools
|
46
|
+
def factory(element_xml)
|
47
|
+
OpenNebula::VirtualMachine.new(element_xml,@client)
|
48
|
+
end
|
49
|
+
|
50
|
+
#######################################################################
|
51
|
+
# XML-RPC Methods for the Virtual Network Object
|
52
|
+
#######################################################################
|
53
|
+
|
54
|
+
# Retrieves all or part of the VirtualMachines in the pool.
|
55
|
+
# No arguments, returns the not-in-done VMs for the user
|
56
|
+
# [user_id, start_id, end_id]
|
57
|
+
# [user_id, start_id, end_id, state]
|
58
|
+
def info(*args)
|
59
|
+
case args.size
|
60
|
+
when 0
|
61
|
+
info_filter(VM_POOL_METHODS[:info],
|
62
|
+
@user_id,
|
63
|
+
-1,
|
64
|
+
-1,
|
65
|
+
INFO_NOT_DONE)
|
66
|
+
when 1
|
67
|
+
info_filter(VM_POOL_METHODS[:info],
|
68
|
+
args[0],
|
69
|
+
-1,
|
70
|
+
-1,
|
71
|
+
INFO_NOT_DONE)
|
72
|
+
when 3
|
73
|
+
info_filter(VM_POOL_METHODS[:info],
|
74
|
+
args[0],
|
75
|
+
args[1],
|
76
|
+
args[2],
|
77
|
+
INFO_NOT_DONE)
|
78
|
+
when 4
|
79
|
+
info_filter(VM_POOL_METHODS[:info],
|
80
|
+
args[0],
|
81
|
+
args[1],
|
82
|
+
args[2],
|
83
|
+
args[3])
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def info_all()
|
88
|
+
return info_filter(VM_POOL_METHODS[:info],
|
89
|
+
INFO_ALL,
|
90
|
+
-1,
|
91
|
+
-1,
|
92
|
+
INFO_NOT_DONE)
|
93
|
+
end
|
94
|
+
|
95
|
+
def info_mine()
|
96
|
+
return info_filter(VM_POOL_METHODS[:info],
|
97
|
+
INFO_MINE,
|
98
|
+
-1,
|
99
|
+
-1,
|
100
|
+
INFO_NOT_DONE)
|
101
|
+
end
|
102
|
+
|
103
|
+
def info_group()
|
104
|
+
return info_filter(VM_POOL_METHODS[:info],
|
105
|
+
INFO_GROUP,
|
106
|
+
-1,
|
107
|
+
-1,
|
108
|
+
INFO_NOT_DONE)
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
|
113
|
+
def info_filter(xml_method, who, start_id, end_id, state)
|
114
|
+
return xmlrpc_info(xml_method, who, start_id, end_id, state)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
# -------------------------------------------------------------------------- #
|
2
|
+
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
|
3
|
+
# #
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
5
|
+
# not use this file except in compliance with the License. You may obtain #
|
6
|
+
# a copy of the License at #
|
7
|
+
# #
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0 #
|
9
|
+
# #
|
10
|
+
# Unless required by applicable law or agreed to in writing, software #
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS, #
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
13
|
+
# See the License for the specific language governing permissions and #
|
14
|
+
# limitations under the License. #
|
15
|
+
#--------------------------------------------------------------------------- #
|
16
|
+
|
17
|
+
require 'OpenNebula/Pool'
|
18
|
+
|
19
|
+
module OpenNebula
|
20
|
+
class VirtualNetwork < PoolElement
|
21
|
+
# ---------------------------------------------------------------------
|
22
|
+
# Constants and Class Methods
|
23
|
+
# ---------------------------------------------------------------------
|
24
|
+
VN_METHODS = {
|
25
|
+
:info => "vn.info",
|
26
|
+
:allocate => "vn.allocate",
|
27
|
+
:publish => "vn.publish",
|
28
|
+
:delete => "vn.delete",
|
29
|
+
:addleases => "vn.addleases",
|
30
|
+
:rmleases => "vn.rmleases",
|
31
|
+
:chown => "vn.chown"
|
32
|
+
}
|
33
|
+
|
34
|
+
VN_TYPES=%w{RANGED FIXED}
|
35
|
+
|
36
|
+
SHORT_VN_TYPES={
|
37
|
+
"RANGED" => "R",
|
38
|
+
"FIXED" => "F"
|
39
|
+
}
|
40
|
+
|
41
|
+
# Creates a VirtualNetwork description with just its identifier
|
42
|
+
# this method should be used to create plain VirtualNetwork objects.
|
43
|
+
# +id+ the id of the network
|
44
|
+
#
|
45
|
+
# Example:
|
46
|
+
# vnet = VirtualNetwork.new(VirtualNetwork.build_xml(3),rpc_client)
|
47
|
+
#
|
48
|
+
def VirtualNetwork.build_xml(pe_id=nil)
|
49
|
+
if pe_id
|
50
|
+
vn_xml = "<VNET><ID>#{pe_id}</ID></VNET>"
|
51
|
+
else
|
52
|
+
vn_xml = "<VNET></VNET>"
|
53
|
+
end
|
54
|
+
|
55
|
+
XMLElement.build_xml(vn_xml, 'VNET')
|
56
|
+
end
|
57
|
+
|
58
|
+
# Class constructor
|
59
|
+
def initialize(xml, client)
|
60
|
+
super(xml,client)
|
61
|
+
|
62
|
+
@client = client
|
63
|
+
end
|
64
|
+
|
65
|
+
#######################################################################
|
66
|
+
# XML-RPC Methods for the Virtual Network Object
|
67
|
+
#######################################################################
|
68
|
+
|
69
|
+
# Retrieves the information of the given VirtualNetwork.
|
70
|
+
def info()
|
71
|
+
super(VN_METHODS[:info], 'VNET')
|
72
|
+
end
|
73
|
+
|
74
|
+
# Allocates a new VirtualNetwork in OpenNebula
|
75
|
+
#
|
76
|
+
# +description+ A string containing the template of the VirtualNetwork.
|
77
|
+
def allocate(description)
|
78
|
+
super(VN_METHODS[:allocate],description)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Publishes the VirtualNetwork, to be used by other users
|
82
|
+
def publish
|
83
|
+
set_publish(true)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Unplubishes the VirtualNetwork
|
87
|
+
def unpublish
|
88
|
+
set_publish(false)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Deletes the VirtualNetwork
|
92
|
+
def delete()
|
93
|
+
super(VN_METHODS[:delete])
|
94
|
+
end
|
95
|
+
|
96
|
+
# Adds a lease to the VirtualNetwork
|
97
|
+
def addleases(ip, mac = nil)
|
98
|
+
return Error.new('ID not defined') if !@pe_id
|
99
|
+
|
100
|
+
lease_template = "LEASES = [ IP = #{ip}"
|
101
|
+
lease_template << ", MAC = #{mac}" if mac
|
102
|
+
lease_template << " ]"
|
103
|
+
|
104
|
+
rc = @client.call(VN_METHODS[:addleases], @pe_id, lease_template)
|
105
|
+
rc = nil if !OpenNebula.is_error?(rc)
|
106
|
+
|
107
|
+
return rc
|
108
|
+
end
|
109
|
+
|
110
|
+
# Removes a lease from the VirtualNetwork
|
111
|
+
def rmleases(ip)
|
112
|
+
return Error.new('ID not defined') if !@pe_id
|
113
|
+
|
114
|
+
lease_template = "LEASES = [ IP = #{ip} ]"
|
115
|
+
|
116
|
+
rc = @client.call(VN_METHODS[:rmleases], @pe_id, lease_template)
|
117
|
+
rc = nil if !OpenNebula.is_error?(rc)
|
118
|
+
|
119
|
+
return rc
|
120
|
+
end
|
121
|
+
|
122
|
+
# Changes the owner/group
|
123
|
+
# uid:: _Integer_ the new owner id. Set to -1 to leave the current one
|
124
|
+
# gid:: _Integer_ the new group id. Set to -1 to leave the current one
|
125
|
+
# [return] nil in case of success or an Error object
|
126
|
+
def chown(uid, gid)
|
127
|
+
super(VN_METHODS[:chown], uid, gid)
|
128
|
+
end
|
129
|
+
|
130
|
+
# ---------------------------------------------------------------------
|
131
|
+
# Helpers to get VirtualNetwork information
|
132
|
+
# ---------------------------------------------------------------------
|
133
|
+
|
134
|
+
# Returns the group identifier
|
135
|
+
# [return] _Integer_ the element's group ID
|
136
|
+
def gid
|
137
|
+
self['GID'].to_i
|
138
|
+
end
|
139
|
+
|
140
|
+
# Returns the type of the Virtual Network (numeric value)
|
141
|
+
def type
|
142
|
+
self['TYPE'].to_i
|
143
|
+
end
|
144
|
+
|
145
|
+
# Returns the type of the Virtual Network (string value)
|
146
|
+
def type_str
|
147
|
+
VN_TYPES[type]
|
148
|
+
end
|
149
|
+
|
150
|
+
# Returns the state of the Virtual Network (string value)
|
151
|
+
def short_type_str
|
152
|
+
SHORT_VN_TYPES[type_str]
|
153
|
+
end
|
154
|
+
|
155
|
+
private
|
156
|
+
def set_publish(published)
|
157
|
+
return Error.new('ID not defined') if !@pe_id
|
158
|
+
|
159
|
+
rc = @client.call(VN_METHODS[:publish], @pe_id, published)
|
160
|
+
rc = nil if !OpenNebula.is_error?(rc)
|
161
|
+
|
162
|
+
return rc
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# -------------------------------------------------------------------------- #
|
2
|
+
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
|
3
|
+
# #
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
5
|
+
# not use this file except in compliance with the License. You may obtain #
|
6
|
+
# a copy of the License at #
|
7
|
+
# #
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0 #
|
9
|
+
# #
|
10
|
+
# Unless required by applicable law or agreed to in writing, software #
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS, #
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
13
|
+
# See the License for the specific language governing permissions and #
|
14
|
+
# limitations under the License. #
|
15
|
+
#--------------------------------------------------------------------------- #
|
16
|
+
|
17
|
+
require 'OpenNebula/Pool'
|
18
|
+
|
19
|
+
module OpenNebula
|
20
|
+
class VirtualNetworkPool < Pool
|
21
|
+
#######################################################################
|
22
|
+
# Constants and Class attribute accessors
|
23
|
+
#######################################################################
|
24
|
+
|
25
|
+
VN_POOL_METHODS = {
|
26
|
+
:info => "vnpool.info"
|
27
|
+
}
|
28
|
+
|
29
|
+
#######################################################################
|
30
|
+
# Class constructor & Pool Methods
|
31
|
+
#######################################################################
|
32
|
+
|
33
|
+
# +client+ a Client object that represents a XML-RPC connection
|
34
|
+
# +user_id+ is to refer to a Pool with VirtualNetworks from that user
|
35
|
+
def initialize(client, user_id=0)
|
36
|
+
super('VNET_POOL','VNET',client)
|
37
|
+
|
38
|
+
@user_id = user_id
|
39
|
+
end
|
40
|
+
|
41
|
+
# Default Factory Method for the Pools
|
42
|
+
def factory(element_xml)
|
43
|
+
OpenNebula::VirtualNetwork.new(element_xml,@client)
|
44
|
+
end
|
45
|
+
|
46
|
+
#######################################################################
|
47
|
+
# XML-RPC Methods for the Virtual Network Object
|
48
|
+
#######################################################################
|
49
|
+
|
50
|
+
# Retrieves all or part of the VirtualMachines in the pool.
|
51
|
+
def info(*args)
|
52
|
+
case args.size
|
53
|
+
when 0
|
54
|
+
info_filter(VN_POOL_METHODS[:info],@user_id,-1,-1)
|
55
|
+
when 3
|
56
|
+
info_filter(VN_POOL_METHODS[:info],args[0],args[1],args[2])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def info_all()
|
61
|
+
return super(VN_POOL_METHODS[:info])
|
62
|
+
end
|
63
|
+
|
64
|
+
def info_mine()
|
65
|
+
return super(VN_POOL_METHODS[:info])
|
66
|
+
end
|
67
|
+
|
68
|
+
def info_group()
|
69
|
+
return super(VN_POOL_METHODS[:info])
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,340 @@
|
|
1
|
+
# -------------------------------------------------------------------------- #
|
2
|
+
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
|
3
|
+
# #
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
5
|
+
# not use this file except in compliance with the License. You may obtain #
|
6
|
+
# a copy of the License at #
|
7
|
+
# #
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0 #
|
9
|
+
# #
|
10
|
+
# Unless required by applicable law or agreed to in writing, software #
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS, #
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
13
|
+
# See the License for the specific language governing permissions and #
|
14
|
+
# limitations under the License. #
|
15
|
+
#--------------------------------------------------------------------------- #
|
16
|
+
|
17
|
+
module OpenNebula
|
18
|
+
|
19
|
+
begin
|
20
|
+
require 'nokogiri'
|
21
|
+
NOKOGIRI=true
|
22
|
+
rescue LoadError
|
23
|
+
NOKOGIRI=false
|
24
|
+
end
|
25
|
+
|
26
|
+
begin
|
27
|
+
require 'rexml/formatters/pretty'
|
28
|
+
REXML_FORMATTERS=true
|
29
|
+
rescue LoadError
|
30
|
+
REXML_FORMATTERS=false
|
31
|
+
end
|
32
|
+
|
33
|
+
###########################################################################
|
34
|
+
# The XMLElement class provides an abstraction of the underlying
|
35
|
+
# XML parser engine. It provides XML-related methods for the Pool and
|
36
|
+
# PoolElement classes
|
37
|
+
###########################################################################
|
38
|
+
class XMLElement
|
39
|
+
|
40
|
+
# xml:: _opaque xml object_ an xml object as returned by build_xml
|
41
|
+
def initialize(xml=nil)
|
42
|
+
@xml = xml
|
43
|
+
end
|
44
|
+
|
45
|
+
# Initialize a XML document for the element
|
46
|
+
# xml:: _String_ the XML document of the object
|
47
|
+
# root_element:: _String_ Base xml element
|
48
|
+
def initialize_xml(xml, root_element)
|
49
|
+
@xml = XMLElement.build_xml(xml, root_element)
|
50
|
+
|
51
|
+
if OpenNebula.is_error?(@xml)
|
52
|
+
@xml = nil
|
53
|
+
else
|
54
|
+
if NOKOGIRI
|
55
|
+
if @xml.size == 0
|
56
|
+
@xml = nil
|
57
|
+
end
|
58
|
+
else
|
59
|
+
if @xml.name != root_element
|
60
|
+
@xml = nil
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Builds a XML document
|
67
|
+
# xml:: _String_ the XML document of the object
|
68
|
+
# root_element:: _String_ Base xml element
|
69
|
+
# [return] _XML_ object for the underlying XML engine
|
70
|
+
def self.build_xml(xml, root_element)
|
71
|
+
begin
|
72
|
+
if NOKOGIRI
|
73
|
+
doc = Nokogiri::XML(xml).xpath("/#{root_element}")
|
74
|
+
else
|
75
|
+
doc = REXML::Document.new(xml).root
|
76
|
+
end
|
77
|
+
rescue Exception => e
|
78
|
+
return OpenNebula::Error.new(e.message)
|
79
|
+
end
|
80
|
+
|
81
|
+
return doc
|
82
|
+
end
|
83
|
+
# Extract an element from the XML description of the PoolElement.
|
84
|
+
# key::_String_ The name of the element
|
85
|
+
# [return] _String_ the value of the element
|
86
|
+
# Examples:
|
87
|
+
# ['VID'] # gets VM id
|
88
|
+
# ['HISTORY/HOSTNAME'] # get the hostname from the history
|
89
|
+
def [](key)
|
90
|
+
if NOKOGIRI
|
91
|
+
element=@xml.xpath(key.to_s)
|
92
|
+
|
93
|
+
if element.size == 0
|
94
|
+
return nil
|
95
|
+
end
|
96
|
+
else
|
97
|
+
element=@xml.elements[key.to_s]
|
98
|
+
end
|
99
|
+
|
100
|
+
if element
|
101
|
+
element.text
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Gets an array of text from elemenets extracted
|
106
|
+
# using the XPATH expression passed as filter
|
107
|
+
def retrieve_elements(filter)
|
108
|
+
elements_array = Array.new
|
109
|
+
|
110
|
+
if NOKOGIRI
|
111
|
+
@xml.xpath(filter.to_s).each { |pelem|
|
112
|
+
elements_array << pelem.text if pelem.text
|
113
|
+
}
|
114
|
+
else
|
115
|
+
@xml.elements.each(filter.to_s) { |pelem|
|
116
|
+
elements_array << pelem.text if pelem.text
|
117
|
+
}
|
118
|
+
end
|
119
|
+
|
120
|
+
if elements_array.size == 0
|
121
|
+
return nil
|
122
|
+
else
|
123
|
+
return elements_array
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
# Gets an attribute from an elemenT
|
129
|
+
# key:: _String_ xpath for the element
|
130
|
+
# name:: _String_ name of the attribute
|
131
|
+
def attr(key,name)
|
132
|
+
value = nil
|
133
|
+
|
134
|
+
if NOKOGIRI
|
135
|
+
element=@xml.xpath(key.to_s.upcase)
|
136
|
+
if element.size == 0
|
137
|
+
return nil
|
138
|
+
end
|
139
|
+
|
140
|
+
attribute = element.attr(name)
|
141
|
+
|
142
|
+
value = attribute.text if attribute != nil
|
143
|
+
else
|
144
|
+
element=@xml.elements[key.to_s.upcase]
|
145
|
+
|
146
|
+
value = element.attributes[name] if element != nil
|
147
|
+
end
|
148
|
+
|
149
|
+
return value
|
150
|
+
end
|
151
|
+
|
152
|
+
# Iterates over every Element in the XPath and calls the block with a
|
153
|
+
# a XMLElement
|
154
|
+
# block:: _Block_
|
155
|
+
def each(xpath_str,&block)
|
156
|
+
if NOKOGIRI
|
157
|
+
@xml.xpath(xpath_str).each { |pelem|
|
158
|
+
block.call XMLElement.new(pelem)
|
159
|
+
}
|
160
|
+
else
|
161
|
+
@xml.elements.each(xpath_str) { |pelem|
|
162
|
+
block.call XMLElement.new(pelem)
|
163
|
+
}
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def each_xpath(xpath_str,&block)
|
168
|
+
if NOKOGIRI
|
169
|
+
@xml.xpath(xpath_str).each { |pelem|
|
170
|
+
block.call pelem.text
|
171
|
+
}
|
172
|
+
else
|
173
|
+
@xml.elements.each(xpath_str) { |pelem|
|
174
|
+
block.call pelem.text
|
175
|
+
}
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def name
|
180
|
+
@xml.name
|
181
|
+
end
|
182
|
+
|
183
|
+
def text
|
184
|
+
if NOKOGIRI
|
185
|
+
@xml.content
|
186
|
+
else
|
187
|
+
@xml.text
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def has_elements?(xpath_str)
|
192
|
+
if NOKOGIRI
|
193
|
+
element = @xml.xpath(xpath_str.to_s.upcase)
|
194
|
+
return element != nil && element.children.size > 0
|
195
|
+
else
|
196
|
+
element = @xml.elements[xpath_str.to_s]
|
197
|
+
return element != nil && element.has_elements?
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def template_str(indent=true)
|
202
|
+
template_like_str('TEMPLATE', indent)
|
203
|
+
end
|
204
|
+
|
205
|
+
def template_like_str(root_element, indent=true)
|
206
|
+
if NOKOGIRI
|
207
|
+
xml_template=@xml.xpath(root_element).to_s
|
208
|
+
rexml=REXML::Document.new(xml_template).root
|
209
|
+
else
|
210
|
+
rexml=@xml.elements[root_element]
|
211
|
+
end
|
212
|
+
|
213
|
+
if indent
|
214
|
+
ind_enter="\n"
|
215
|
+
ind_tab=' '
|
216
|
+
else
|
217
|
+
ind_enter=''
|
218
|
+
ind_tab=' '
|
219
|
+
end
|
220
|
+
|
221
|
+
str=rexml.collect {|n|
|
222
|
+
if n.class==REXML::Element
|
223
|
+
str_line=""
|
224
|
+
if n.has_elements?
|
225
|
+
str_line << n.name << "=[" << ind_enter
|
226
|
+
|
227
|
+
str_line << n.collect {|n2|
|
228
|
+
if n2 && n2.class==REXML::Element
|
229
|
+
str = ""
|
230
|
+
str << ind_tab << n2.name << '='
|
231
|
+
str << attr_to_str(n2.text) if n2.text
|
232
|
+
str
|
233
|
+
end
|
234
|
+
}.compact.join(','+ind_enter)
|
235
|
+
str_line<<" ]"
|
236
|
+
else
|
237
|
+
str_line << n.name << '=' << attr_to_str(n.text.to_s)
|
238
|
+
end
|
239
|
+
str_line
|
240
|
+
end
|
241
|
+
}.compact.join("\n")
|
242
|
+
|
243
|
+
str
|
244
|
+
end
|
245
|
+
|
246
|
+
def to_xml(pretty=false)
|
247
|
+
if NOKOGIRI && pretty
|
248
|
+
str = @xml.to_xml
|
249
|
+
elsif REXML_FORMATTERS && pretty
|
250
|
+
str = String.new
|
251
|
+
|
252
|
+
formatter = REXML::Formatters::Pretty.new
|
253
|
+
formatter.compact = true
|
254
|
+
|
255
|
+
formatter.write(@xml,str)
|
256
|
+
else
|
257
|
+
str = @xml.to_s
|
258
|
+
end
|
259
|
+
|
260
|
+
return str
|
261
|
+
end
|
262
|
+
|
263
|
+
def to_hash(hash={}, element=nil)
|
264
|
+
element ||= @xml.document.root
|
265
|
+
|
266
|
+
if NOKOGIRI
|
267
|
+
array = element.children
|
268
|
+
if array.length==1 and (array.first.text? or array.first.cdata?)
|
269
|
+
r = array.first.text
|
270
|
+
else
|
271
|
+
r = {}
|
272
|
+
array.each { |c|
|
273
|
+
if c.element?
|
274
|
+
to_hash(r, c)
|
275
|
+
end
|
276
|
+
}
|
277
|
+
end
|
278
|
+
else
|
279
|
+
r = {}
|
280
|
+
if element.has_elements?
|
281
|
+
element.each_element { |c| to_hash(r, c) }
|
282
|
+
elsif element.has_text?
|
283
|
+
r = element.text
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
key = element.name
|
288
|
+
if hash.has_key?(key)
|
289
|
+
if hash[key].instance_of?(Array)
|
290
|
+
hash[key] << r
|
291
|
+
else
|
292
|
+
hash[key] = [hash[key], r]
|
293
|
+
end
|
294
|
+
else
|
295
|
+
hash[key] = r
|
296
|
+
end
|
297
|
+
|
298
|
+
hash
|
299
|
+
end
|
300
|
+
|
301
|
+
private
|
302
|
+
def attr_to_str(attr)
|
303
|
+
attr.gsub!('"',"\\\"")
|
304
|
+
|
305
|
+
if attr.match(/[=,' ']/)
|
306
|
+
return '"' + attr + '"'
|
307
|
+
end
|
308
|
+
|
309
|
+
return attr
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
###########################################################################
|
314
|
+
# The XMLUtilsPool module provides an abstraction of the underlying
|
315
|
+
# XML parser engine. It provides XML-related methods for the Pools
|
316
|
+
###########################################################################
|
317
|
+
class XMLPool < XMLElement
|
318
|
+
|
319
|
+
def initialize(xml=nil)
|
320
|
+
super(xml)
|
321
|
+
end
|
322
|
+
|
323
|
+
#Executes the given block for each element of the Pool
|
324
|
+
#block:: _Block_
|
325
|
+
def each_element(block)
|
326
|
+
if NOKOGIRI
|
327
|
+
@xml.xpath(
|
328
|
+
"#{@element_name}").each {|pelem|
|
329
|
+
block.call self.factory(pelem)
|
330
|
+
}
|
331
|
+
else
|
332
|
+
@xml.elements.each(
|
333
|
+
"#{@element_name}") {|pelem|
|
334
|
+
block.call self.factory(pelem)
|
335
|
+
}
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
end
|