1
2
3 """
4 ::
5
6 Copyright 2010 Glencoe Software, Inc. All rights reserved.
7 Use is subject to license terms supplied in LICENSE.txt
8
9 """
10
11 """
12 Module which parses an icegrid XML file for configuration settings.
13
14 see ticket:800
15 see ticket:2213 - Replacing Java Preferences API
16 """
17
18 import re
19 import os
20 import path
21 import time
22 import logging
23 import exceptions
24 import portalocker
25
26 import xml.dom.minidom
27
28 try:
29 from xml.etree.ElementTree import XML, Element, SubElement, Comment, ElementTree, tostring
30 except ImportError:
31 from elementtree.ElementTree import XML, Element, SubElement, Comment, ElementTree, tostring
32
33
35 """
36
37 """
38 KEY = "omero.config.version"
39 VERSION = "4.2.1"
40 INTERNAL = "__ACTIVE__"
41 DEFAULT = "omero.config.profile"
42 IGNORE = (KEY, DEFAULT)
43
44 - def __init__(self, filename, env_config = None, exclusive = True):
45 self.logger = logging.getLogger(self.__class__.__name__)
46 self.XML = None
47 self.env_config = env_config
48 self.filename = filename
49 self.source = open(filename, "a+")
50 self.lock = self._open_lock()
51 self.exclusive = exclusive
52 try:
53 self._CloseEx = WindowsError
54 except NameError:
55 self._CloseEx = None
56 if exclusive:
57 try:
58 portalocker.lock(self.lock, portalocker.LOCK_NB|portalocker.LOCK_EX)
59 except portalocker.LockException, le:
60 self.lock = None
61 self.close()
62 raise
63
64 self.source.seek(0)
65 text = self.source.read()
66
67 if text:
68 self.XML = XML(text)
69 try:
70 self.version_check()
71 except:
72 self.close()
73 raise
74
75
76 if self.XML is None:
77 default = self.default()
78 self.XML = Element("icegrid")
79 properties = SubElement(self.XML, "properties", id=self.INTERNAL)
80 _ = SubElement(properties, "property", name=self.DEFAULT, value=default)
81 _ = SubElement(properties, "property", name=self.KEY, value=self.VERSION)
82 properties = SubElement(self.XML, "properties", id=default)
83 _ = SubElement(properties, "property", name=self.KEY, value=self.VERSION)
84
86 return open("%s.lock" % self.filename, "a+")
87
89 if self.lock is not None:
90 self.lock.close()
91 try:
92 os.remove("%s.lock" % self.filename)
93 except:
94
95 self.logger.error("Failed to removed lock file, ignoring", exc_info=True)
96 pass
97
106
112
114 """
115 Currently we are assuming that all blocks without a 4.2.0 version
116 are bogus. The configuration script when it generates an initial
117 config.xml will use prefs.class to parse the existing values and
118 immediately do the upgrade.
119 """
120 if version == "4.2.0":
121
122
123
124 if props:
125 for x in props.getchildren():
126 if x.get("name", "").startswith("omero.ldap"):
127 orig = x.get("value", "")
128 val = orig.replace("${omero.dollar}", "")
129 val = val.replace("${", "@{")
130 x.set("value", val)
131 self.logger.info("Upgraded 4.2.0 property: %s => %s", orig, val)
132 else:
133 raise exceptions.Exception("Version mismatch: %s has %s" % (props.get("id"), version))
134
137
138 - def properties(self, id = None, filter_internal = False):
139
140 if self.XML is None:
141 return None
142
143 props = self.XML.findall("./properties")
144 if id is None:
145 rv = list()
146 for x in props:
147 id = x.attrib["id"]
148 if filter_internal:
149 if id == self.INTERNAL:
150 continue
151 rv.append((id, x))
152 return rv
153 for p in props:
154 if "id" in p.attrib and p.attrib["id"] == id:
155 return p
156
164
166 if value:
167 self.env_config = value
168 if self.env_config:
169 return self.env_config
170 elif "OMERO_CONFIG" in os.environ:
171 return os.environ["OMERO_CONFIG"]
172 else:
173
174
175
176
177
178
179 return "default"
180
187
189 """
190 Creates a fresh <icegrid> block (removing any unwanted
191 intra-element whitespace) and overwrites the file on disk.
192 """
193 icegrid = Element("icegrid")
194 comment = Comment("\n".join(["\n",
195 "\tThis file was generated at %s by the OmeroConfig system.",
196 "\tDo not edit directly but see bin/omero config for details.",
197 "\tThis file may be included into your IceGrid application.",
198 "\n"]) % time.ctime())
199 icegrid.append(comment)
200
201
202
203 default = self.default()
204 internal = SubElement(icegrid, "properties", id=self.INTERNAL)
205 SubElement(internal, "property", name=self.DEFAULT, value=default)
206 SubElement(internal, "property", name=self.KEY, value=self.VERSION)
207 to_copy = self.properties(default)
208 if to_copy is not None:
209 for x in to_copy.getchildren():
210 if x.get("name") != self.DEFAULT and x.get("name") != self.KEY:
211 SubElement(internal, "property", x.attrib)
212 else:
213
214 properties = SubElement(icegrid, "properties", id=default)
215 SubElement(properties, "property", name=self.KEY, value=self.VERSION)
216
217 prop_list = self.properties(None, True)
218 for k, p in prop_list:
219 self.clear_text(p)
220 icegrid.append(p)
221 self.source.seek(0)
222 self.source.truncate()
223 self.source.write(self.element_to_xml(icegrid))
224 self.source.flush()
225
227 try:
228
229
230
231 if self.XML is not None:
232 self.save()
233 finally:
234 try:
235 self.source.close()
236 finally:
237 self._close_lock()
238
240
241 if c is None:
242 return {}
243
244 rv = dict()
245 props = c.findall("./property")
246 for p in props:
247 if "name" in p.attrib:
248 rv[p.attrib["name"]] = p.attrib.get("value", "")
249 return rv
250
251 - def dict_to_text(self, parsed = None):
252
253 if parsed is None:
254 return
255
256 rv = ""
257 for k, v in parsed.items():
258 rv += "%s=%s" % (k, v)
259 return rv
260
262 string = tostring(elem, 'utf-8')
263 return xml.dom.minidom.parseString(string).toprettyxml(" ", "\n", None)
264
265 - def clear_text(self, p):
266 """
267 To prevent the accumulation of text outside of elements (including whitespace)
268 we walk the given element and remove tail from it and it's children.
269 """
270 p.tail = ""
271 p.text = ""
272 for p2 in p.getchildren():
273 self.clear_text(p2)
274
275
276
277
280
283
286
299
309