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 = open("%s.lock" % filename, "a+")
51 self.exclusive = exclusive
52 if exclusive:
53 try:
54 portalocker.lock(self.lock, portalocker.LOCK_NB|portalocker.LOCK_EX)
55 except portalocker.LockException, le:
56 self.close()
57 raise
58
59 self.source.seek(0)
60 text = self.source.read()
61
62 if text:
63 self.XML = XML(text)
64 try:
65 self.version_check()
66 except:
67 self.close()
68 raise
69
70
71 if not self.XML:
72 default = self.default()
73 self.XML = Element("icegrid")
74 properties = SubElement(self.XML, "properties", id=self.INTERNAL)
75 _ = SubElement(properties, "property", name=self.DEFAULT, value=default)
76 _ = SubElement(properties, "property", name=self.KEY, value=self.VERSION)
77 properties = SubElement(self.XML, "properties", id=default)
78 _ = SubElement(properties, "property", name=self.KEY, value=self.VERSION)
79
88
94
96 """
97 Currently we are assuming that all blocks without a 4.2.0 version
98 are bogus. The configuration script when it generates an initial
99 config.xml will use prefs.class to parse the existing values and
100 immediately do the upgrade.
101 """
102 if version == "4.2.0":
103
104
105
106 if props:
107 for x in props.getchildren():
108 if x.get("name", "").startswith("omero.ldap"):
109 orig = x.get("value", "")
110 val = orig.replace("${omero.dollar}", "")
111 val = val.replace("${", "@{")
112 x.set("value", val)
113 self.logger.info("Upgraded 4.2.0 property: %s => %s", orig, val)
114 else:
115 raise exceptions.Exception("Version mismatch: %s has %s" % (props.get("id"), version))
116
119
120 - def properties(self, id = None, filter_internal = False):
121
122 if not self.XML:
123 return None
124
125 props = self.XML.findall("./properties")
126 if id is None:
127 rv = list()
128 for x in props:
129 id = x.attrib["id"]
130 if filter_internal:
131 if id == self.INTERNAL:
132 continue
133 rv.append((id, x))
134 return rv
135 for p in props:
136 if "id" in p.attrib and p.attrib["id"] == id:
137 return p
138
146
148 if value:
149 self.env_config = value
150 if self.env_config:
151 return self.env_config
152 elif "OMERO_CONFIG" in os.environ:
153 return os.environ["OMERO_CONFIG"]
154 else:
155
156
157
158
159
160
161 return "default"
162
169
171 """
172 Creates a fresh <icegrid> block (removing any unwanted
173 intra-element whitespace) and overwrites the file on disk.
174 """
175 icegrid = Element("icegrid")
176 comment = Comment("\n".join(["\n",
177 "\tThis file was generated at %s by the OmeroConfig system.",
178 "\tDo not edit directly but see bin/omero config for details.",
179 "\tThis file may be included into your IceGrid application.",
180 "\n"]) % time.ctime())
181 icegrid.append(comment)
182
183
184
185 default = self.default()
186 internal = SubElement(icegrid, "properties", id=self.INTERNAL)
187 SubElement(internal, "property", name=self.DEFAULT, value=default)
188 SubElement(internal, "property", name=self.KEY, value=self.VERSION)
189 to_copy = self.properties(default)
190 if to_copy is not None:
191 for x in to_copy.getchildren():
192 if x.get("name") != self.DEFAULT and x.get("name") != self.KEY:
193 SubElement(internal, "property", x.attrib)
194 else:
195
196 properties = SubElement(icegrid, "properties", id=default)
197 SubElement(properties, "property", name=self.KEY, value=self.VERSION)
198
199 prop_list = self.properties(None, True)
200 for k, p in prop_list:
201 self.clear_text(p)
202 icegrid.append(p)
203 self.source.seek(0)
204 self.source.truncate()
205 self.source.write(self.element_to_xml(icegrid))
206 self.source.flush()
207
209 try:
210
211
212
213 if self.XML:
214 self.save()
215 finally:
216 try:
217 self.source.close()
218 finally:
219 self.lock.close()
220
222
223 if c is None:
224 return {}
225
226 rv = dict()
227 props = c.findall("./property")
228 for p in props:
229 if "name" in p.attrib:
230 rv[p.attrib["name"]] = p.attrib.get("value", "")
231 return rv
232
233 - def dict_to_text(self, parsed = None):
234
235 if parsed is None:
236 return
237
238 rv = ""
239 for k, v in parsed.items():
240 rv += "%s=%s" % (k, v)
241 return rv
242
244 string = tostring(elem, 'utf-8')
245 return xml.dom.minidom.parseString(string).toprettyxml(" ", "\n", None)
246
247 - def clear_text(self, p):
248 """
249 To prevent the accumulation of text outside of elements (including whitespace)
250 we walk the given element and remove tail from it and it's children.
251 """
252 p.tail = ""
253 p.text = ""
254 for p2 in p.getchildren():
255 self.clear_text(p2)
256
257
258
259
262
265
268
281
291