• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

evolvedbinary / elemental / 982

29 Apr 2025 08:34PM UTC coverage: 56.409% (+0.007%) from 56.402%
982

push

circleci

adamretter
[feature] Improve README.md badges

28451 of 55847 branches covered (50.94%)

Branch coverage included in aggregate %.

77468 of 131924 relevant lines covered (58.72%)

0.59 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

63.29
/exist-core/src/main/java/org/exist/config/ConfigurationImpl.java
1
/*
2
 * Elemental
3
 * Copyright (C) 2024, Evolved Binary Ltd
4
 *
5
 * admin@evolvedbinary.com
6
 * https://www.evolvedbinary.com | https://www.elemental.xyz
7
 *
8
 * Use of this software is governed by the Business Source License 1.1
9
 * included in the LICENSE file and at www.mariadb.com/bsl11.
10
 *
11
 * Change Date: 2028-04-27
12
 *
13
 * On the date above, in accordance with the Business Source License, use
14
 * of this software will be governed by the Apache License, Version 2.0.
15
 *
16
 * Additional Use Grant: Production use of the Licensed Work for a permitted
17
 * purpose. A Permitted Purpose is any purpose other than a Competing Use.
18
 * A Competing Use means making the Software available to others in a commercial
19
 * product or service that: substitutes for the Software; substitutes for any
20
 * other product or service we offer using the Software that exists as of the
21
 * date we make the Software available; or offers the same or substantially
22
 * similar functionality as the Software.
23
 *
24
 * NOTE: Parts of this file contain code from 'The eXist-db Authors'.
25
 *       The original license header is included below.
26
 *
27
 * =====================================================================
28
 *
29
 * eXist-db Open Source Native XML Database
30
 * Copyright (C) 2001 The eXist-db Authors
31
 *
32
 * info@exist-db.org
33
 * http://www.exist-db.org
34
 *
35
 * This library is free software; you can redistribute it and/or
36
 * modify it under the terms of the GNU Lesser General Public
37
 * License as published by the Free Software Foundation; either
38
 * version 2.1 of the License, or (at your option) any later version.
39
 *
40
 * This library is distributed in the hope that it will be useful,
41
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
43
 * Lesser General Public License for more details.
44
 *
45
 * You should have received a copy of the GNU Lesser General Public
46
 * License along with this library; if not, write to the Free Software
47
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
48
 */
49
package org.exist.config;
50

51
import java.lang.ref.WeakReference;
52
import java.util.*;
53

54
import org.exist.dom.persistent.DocumentImpl;
55
import org.exist.security.PermissionDeniedException;
56
import org.exist.storage.DBBroker;
57
import org.w3c.dom.Element;
58
import org.w3c.dom.NamedNodeMap;
59
import org.w3c.dom.Node;
60
import org.w3c.dom.NodeList;
61

62
import javax.xml.XMLConstants;
63

64
/**
65
 * configuration -> element
66
 * property -> attribute
67
 * 
68
 * @author <a href="mailto:shabanovd@gmail.com">Dmitriy Shabanov</a>
69
 *
70
 */
71
public class ConfigurationImpl implements Configuration {
72

73
    private Map<String, Object> runtimeProperties = new HashMap<>();
1✔
74

75
    protected WeakReference<Configurable> configuredObjectReference = null;
1✔
76

77
    private Element element;
78

79
    private ConfigurationImpl() {
×
80
        //Nothing to do
81
    }
×
82

83
    protected ConfigurationImpl(final Element element) {
1✔
84
        this.element = element;
1✔
85
    }
1✔
86

87
    @Override
88
    public Element getElement() {
89
        return element;
1✔
90
    }
91

92
    @Override
93
    public String getName() {
94
        return element.getLocalName();
1✔
95
    }
96

97
    @Override
98
    public String getValue() {
99
        return element.getTextContent();
×
100
    }
101

102
    @Override
103
    public Configuration getConfiguration(String name) {
104
        if (element.getLocalName().equals(name)) {
1✔
105
            return this;
1✔
106
        }
107
        final List<Configuration> list = getConfigurations(name);
1✔
108
        if (list == null)
1!
109
            {return null;}
×
110
        if (list.size() > 0)
1!
111
            {return list.get(0);}
1✔
112
        return null;
×
113
    }
114

115
    @Override
116
    public List<Configuration> getConfigurations(String name) {
117

118
        final List<Configuration> list = new ArrayList<>();
1✔
119
        
120
        Node child = element.getFirstChild();
1✔
121
        while (child != null) {
1✔
122
            
123
            if (child.getNodeType() == Node.ELEMENT_NODE) {
1✔
124

125
                final Element el = (Element)child;
1✔
126

127
                final String ns = el.getNamespaceURI();
1✔
128
                if (name.equals( el.getLocalName() ) && ns != null && NS.equals( ns )) {
1!
129
                    
130
                    final Configuration config = new ConfigurationImpl(el);
1✔
131
                    list.add(config);
1✔
132
                }
133
            }
134
            child = child.getNextSibling();
1✔
135
        }
136
        return list;
1✔
137
    }
138
    
139
    private Map<String, String> props = null;
1✔
140
    
141
    private void cache() {
142
        
143
        if (props != null)
1✔
144
            return;
1✔
145
        
146
        props = new HashMap<>();
1✔
147
        Set<String> names = new HashSet<>();
1✔
148
        
149
        Node child = element.getFirstChild();
1✔
150
        while (child != null) {
1✔
151
            
152
            if (child.getNodeType() == Node.ELEMENT_NODE) {
1✔
153

154
                final String ns = child.getNamespaceURI();
1✔
155
                if (ns != null && NS.equals(ns)) {
1!
156
                    
157
                    String name = child.getLocalName();
1✔
158
                    
159
                    if (names.contains(name)) {
1✔
160
                        
161
                        if (props.containsKey(name)) {
1✔
162
                            props.remove(name);
1✔
163
                        }
164
                    } else {
1✔
165
                        props.put(name, child.getTextContent());
1✔
166
                        names.add(name);
1✔
167
                    }
168
                }
169
            }
170
            child = child.getNextSibling();
1✔
171
        }
172
        
173
        //load attributes values
174
        NamedNodeMap attrs = element.getAttributes();
1✔
175
        for (int i = 0; i < attrs.getLength(); i++) {
1✔
176
            
177
            Node attr = attrs.item(i);
1✔
178
            
179
            if ( !XMLConstants.XMLNS_ATTRIBUTE.equals( attr.getPrefix() ) ) {
1✔
180
                
181
                props.put(attr.getLocalName(), attr.getNodeValue());
1✔
182
            }
183
        }
184
    }
1✔
185
    
186
    public void clearCache() {
187
        props = null;
1✔
188
    }
1✔
189

190
    @Override
191
    public String getProperty(String name) {
192
        
193
        cache();
1✔
194
        
195
        return props.get(name);
1✔
196

197
//        if (hasAttribute(name))
198
//            {return getAttribute(name);}
199
//        final NodeList nodes = getElementsByTagNameNS(NS, name);
200
//        if (nodes.getLength() == 1) {
201
//            return nodes.item(0).getTextContent();
202
//        }
203
//        return null;
204
    }
205

206
    public String getProperty(String name, String default_property) {
207
        final String property = getProperty(name);
×
208
        
209
        if (property == null) return default_property;
×
210
        
211
        return property;
×
212
    }
213

214
    @Override
215
    public Map<String, String> getPropertyMap(String name) {
216
        final Map<String, String> map = new HashMap<>();
1✔
217

218
        if (hasProperty(name)) {
1✔
219
            map.put(name, getProperty(name));
1✔
220
            return map;
1✔
221
        }
222
        
223
        Node child = element.getFirstChild();
1✔
224
        while (child != null) {
1✔
225
            
226
            if (child.getNodeType() == Node.ELEMENT_NODE) {
1✔
227

228
                final Element el = (Element) child;
1✔
229

230
                final String ns = el.getNamespaceURI();
1✔
231
                if (name.equals( el.getLocalName() ) && ns != null && NS.equals( ns )) {
1!
232
                    
233
                    if(!el.hasAttributes()){
1!
234
                        continue;
×
235
                    }
236
                    
237
                    final NamedNodeMap attrs = el.getAttributes();
1✔
238
 
239
                    if (attrs.getLength() != 1) {
1!
240
                        continue;
×
241
                    }
242
                    
243
                    Node attr = attrs.getNamedItem("key");
1✔
244
                    
245
                    if (attr == null)
1!
246
                        continue;
×
247
                    
248
                    final String key = attr.getNodeValue();
1✔
249
                    final String value = el.getTextContent();
1✔
250

251
                    if (key != null && !key.isEmpty() && value != null && !value.isEmpty()) {
1!
252
                        map.put(key, value);
1✔
253
                    }
254
                }
255
            }
256
            child = child.getNextSibling();
1✔
257
        }
258

259
        return map;
1✔
260
        
261
//        if(hasAttribute(name)) {
262
//            return null;
263
//        }
264
//        final Map<String, String> map = new HashMap<String, String>();
265
//        final NodeList nodes = getElementsByTagNameNS(NS, name);
266
//        for(int i = 0; i < nodes.getLength(); i++) {
267
//            final Node item = nodes.item(i);
268
//            if(!item.hasAttributes()){
269
//                return null;
270
//            }
271
//            final NamedNodeMap attrs = item.getAttributes();
272
//            if(attrs.getLength() != 1){
273
//                return null;
274
//            }
275
//            final String key = attrs.getNamedItem("key").getNodeValue();
276
//            final String value = item.getTextContent();
277
//            if(value == null || value.isEmpty()){
278
//                return null;
279
//            }
280
//            map.put(key, value);
281
//        }
282
//        return map;
283
    }
284

285
    @Override
286
    public boolean hasProperty(String name) {
287
        cache();
1✔
288
        
289
        return props.containsKey(name);
1✔
290
        
291
//        if (hasAttribute(name))
292
//            {return true;}
293
//        return (getElementsByTagName(name).getLength() == 1);
294
    }
295

296
    public Object getRuntimeProperty(String name) {
297
        return runtimeProperties.get(name);
×
298
    }
299

300
    public boolean hasRuntimeProperty(String name) {
301
        return runtimeProperties.containsKey(name);
×
302
    }
303

304
    public void setRuntimeProperty(String name, Object obj) {
305
        runtimeProperties.put(name, obj);
×
306
    }
×
307

308
    @Override
309
    public Boolean getPropertyBoolean(final String name) {
310
        final String value = getProperty(name);
1✔
311
        if(value == null) {
1!
312
            return null;
×
313
        }
314
        return switch (value.toLowerCase()) {
1✔
315
            case "yes", "true" -> true;
1✔
316
            case "no", "false" -> false;
1✔
317
            default -> null;
1✔
318
        };
319
    }
320

321
    public Boolean getPropertyBoolean(String name, boolean defaultValue) {
322
        Boolean value = getPropertyBoolean(name);
×
323
        if(value == null) return defaultValue;
×
324

325
        return value;
×
326
    }
327

328
    @Override
329
    public Integer getPropertyInteger(final String name) {
330
        final String value = getProperty(name);
1✔
331
        if (value == null) {
1!
332
            return null;
×
333
        }
334
        return Integer.valueOf(value);
1✔
335
    }
336

337
    public Integer getPropertyInteger(final String name, final Integer defaultValue, final boolean positive) {
338
        final String value = getProperty(name);
×
339
        if (value == null) {
×
340
            return defaultValue;
×
341
        }
342
        final int result = Integer.parseInt(value);
×
343
        if ((positive) && (result < 0)) {
×
344
            return defaultValue;
×
345
        }
346
        return result;
×
347
    }
348

349
    @Override
350
    public Long getPropertyLong(final String name) {
351
        final String value = getProperty(name);
×
352
        if (value == null) {
×
353
            return null;
×
354
        }
355
        return Long.valueOf(value);
×
356
    }
357

358
    public Long getPropertyLong(final String name, final Long defaultValue, final boolean positive) {
359
        final String value = getProperty(name);
×
360
        if (value == null) {
×
361
            return defaultValue;
×
362
        }
363
        final long result = Long.parseLong(value);
×
364
        if ((positive) && (result < 0)) {
×
365
            return defaultValue;
×
366
        }
367
        return result;
×
368
    }
369

370
    public Integer getPropertyMegabytes(String name, Integer defaultValue) {
371
        String cacheMem = element.getAttribute(name);
×
372
        if (!cacheMem.isEmpty()) {
×
373
            if (cacheMem.endsWith("M") || cacheMem.endsWith("m")) {
×
374
                cacheMem = cacheMem.substring(0, cacheMem.length() - 1);
×
375
            }
376
            final Integer result = Integer.valueOf(cacheMem);
×
377
            if (result < 0) {
×
378
                return defaultValue;
×
379
            }
380
            return result;
×
381
        }
382
        return defaultValue;
×
383
    }
384

385
    public String getConfigFilePath() {
386
        return "";//XXX: put config url
×
387
    }
388

389
    @Override
390
    public Set<String> getProperties() {
391
        final Set<String> properties = new HashSet<>();
1✔
392
        final NamedNodeMap attrs = element.getAttributes();
1✔
393
        for (int i = 0; i < attrs.getLength(); i++) {
1✔
394
            //ignore namespace declarations
395
            if ( !XMLConstants.XMLNS_ATTRIBUTE.equals( attrs.item(i).getPrefix() ) )
1✔
396
                {properties.add(attrs.item(i).getNodeName());}
1✔
397
        }
398
        final NodeList children = element.getChildNodes();
1✔
399
        for (int i = 0; i < children.getLength(); i++) {
1✔
400
            final Node child = children.item(i);
1✔
401
            if (child.getNodeType() == Node.ELEMENT_NODE) {
1✔
402
                properties.add(child.getNodeName());
1✔
403
            }
404
        }
405
        return properties;
1✔
406
    }
407

408
    //related objects
409
    Map<String, Object> objects = null;
1✔
410

411
    @Override
412
    public synchronized Object putObject(String name, Object object) {
413
        if (objects == null)
×
414
            objects = new HashMap<>();
×
415
        
416
        return objects.put(name, object);
×
417
    }
418

419
    @Override
420
    public synchronized Object getObject(String name) {
421
        if (objects == null)
×
422
            return null;
×
423
        
424
        return objects.get(name);
×
425
    }
426

427
    private boolean saving = false;
1✔
428

429
    @Override
430
    public void checkForUpdates(Element element) {
431
        synchronized (this) {
1✔
432
            if (!saving && configuredObjectReference != null && configuredObjectReference.get() != null) {
1!
433
                clearCache();
1✔
434
                this.element = element;
1✔
435
                Configurator.configure(configuredObjectReference.get(), this);
1✔
436
            }
437
        }
438
    }
1✔
439

440
    @Override
441
    public void save() throws PermissionDeniedException, ConfigurationException {
442
        //ignore in-memory nodes
443
        if (element instanceof org.exist.dom.memtree.ElementImpl) {
1!
444
            return;
×
445
        }
446

447
        synchronized (this) {
1✔
448
            try {
449
                saving = true;
1✔
450
                if (configuredObjectReference != null && configuredObjectReference.get() != null)
1!
451
                    {Configurator.save(
1✔
452
                        configuredObjectReference.get(),
1✔
453
                        ((DocumentImpl)element.getOwnerDocument()).getURI()
1✔
454
                    );}
455
            } catch (final Exception e) {
1✔
456
               throw new ConfigurationException(e.getMessage(), e);
×
457
            } finally {
458
                saving = false;
1✔
459
            }
460
        }
461
    }
1✔
462

463
    @Override
464
    public void save(final DBBroker broker) throws PermissionDeniedException, ConfigurationException {
465
        //ignore in-memory nodes
466
        if (element instanceof org.exist.dom.memtree.ElementImpl) {
1!
467
            return;
×
468
        }
469

470
        synchronized(this) {
1✔
471
            try {
472
                saving = true;
1✔
473
                if (configuredObjectReference != null && configuredObjectReference.get() != null)
1!
474
                    {Configurator.save(broker,
1✔
475
                        configuredObjectReference.get(),
1✔
476
                        ((DocumentImpl) element.getOwnerDocument()).getURI()
1✔
477
                    );}
478
            } catch (final Exception e) {
1✔
479
               throw new ConfigurationException(e.getMessage(), e);
×
480
            } finally {
481
                saving = false;
1✔
482
            }
483
        }
484
    }
1✔
485

486
    @Override
487
    public boolean equals(final Object obj) {
488
        return equals(obj, Optional.empty());
1✔
489
    }
490

491
    @Override
492
    public boolean equals(final Object obj, final Optional<String> property) {
493
        if (obj instanceof ConfigurationImpl conf) {
1!
494
            if (!(getName().equals(conf.getName()))) {
1✔
495
                return false;
1✔
496
            }
497

498
            final String name = property.orElse(Configuration.ID);
1✔
499
            final Optional<String> value = Optional.ofNullable(getProperty(name));
1✔
500

501
            return value.map(v -> v.equals(conf.getProperty(name))).orElse(false);
1✔
502
        }
503

504
        return false;
×
505
    }
506
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc