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

openmrs / openmrs-core / 16357938490

17 Jul 2025 11:06PM UTC coverage: 65.244% (-0.1%) from 65.359%
16357938490

push

github

web-flow
TRUNK-6318: Add S3 Storage Service (#5110)

111 of 156 new or added lines in 5 files covered. (71.15%)

48 existing lines in 8 files now uncovered.

23568 of 36123 relevant lines covered (65.24%)

0.65 hits per line

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

80.84
/api/src/main/java/org/openmrs/module/Module.java
1
/**
2
 * This Source Code Form is subject to the terms of the Mozilla Public License,
3
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
4
 * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
5
 * the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
6
 *
7
 * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
8
 * graphic logo is a trademark of OpenMRS Inc.
9
 */
10
package org.openmrs.module;
11

12
import java.io.File;
13
import java.util.ArrayList;
14
import java.util.HashMap;
15
import java.util.HashSet;
16
import java.util.IdentityHashMap;
17
import java.util.List;
18
import java.util.Map;
19
import java.util.Properties;
20
import java.util.Set;
21

22
import org.apache.commons.lang3.builder.HashCodeBuilder;
23
import org.openmrs.GlobalProperty;
24
import org.openmrs.Privilege;
25
import org.slf4j.Logger;
26
import org.slf4j.LoggerFactory;
27
import org.w3c.dom.Document;
28

29
/**
30
 * Generic module class that openmrs manipulates
31
 *
32
 * @version 1.0
33
 */
34
public final class Module {
35
        
36
        private static final Logger log = LoggerFactory.getLogger(Module.class);
1✔
37
        
38
        private String name;
39
        
40
        private String moduleId;
41
        
42
        private String packageName;
43
        
44
        private String description;
45
        
46
        private String author;
47
        
48
        private String version;
49
        
50
        private String updateURL; // should be a URL to an update.rdf file
51
        
52
        private String updateVersion = null; // version obtained from the remote update.rdf file
1✔
53
        
54
        private String downloadURL = null; // will only be populated when the remote file is newer than the current module
1✔
55
        
56
        private ModuleActivator moduleActivator;
57
        
58
        private String activatorName;
59
        
60
        private String requireOpenmrsVersion;
61
        
62
        private String requireDatabaseVersion;
63
        
64
        private Map<String, String> requiredModulesMap;
65
        
66
        private Map<String, String> awareOfModulesMap;
67
        
68
        private Map<String, String> startBeforeModulesMap;
69
        
70
        private List<AdvicePoint> advicePoints = new ArrayList<>();
1✔
71
        
72
        private Map<String, String> extensionNames = new IdentityHashMap<>();
1✔
73
        
74
        private List<Extension> extensions = new ArrayList<>();
1✔
75
        
76
        private Map<String, Properties> messages = new HashMap<>();
1✔
77
        
78
        private List<Privilege> privileges = new ArrayList<>();
1✔
79
        
80
        private List<GlobalProperty> globalProperties = new ArrayList<>();
1✔
81
        
82
        private List<String> mappingFiles = new ArrayList<>();
1✔
83
        
84
        private Set<String> packagesWithMappedClasses = new HashSet<>();
1✔
85
        
86
        private String configVersion;
87
        
88
        private Document config = null;
1✔
89
        
90
        private Document sqldiff = null;
1✔
91
        
92
        private boolean mandatory = Boolean.FALSE;
1✔
93
        
94
        private List<ModuleConditionalResource> conditionalResources = new ArrayList<>();
1✔
95
        
96
        // keep a reference to the file that we got this module from so we can delete
97
        // it if necessary
98
        private File file = null;
1✔
99
        
100
        private String startupErrorMessage = null;
1✔
101
        
102
        /**
103
         * Simple constructor
104
         *
105
         * @param name
106
         */
107
        public Module(String name) {
1✔
108
                this.name = name;
1✔
109
        }
1✔
110
        
111
        /**
112
         * Main constructor
113
         *
114
         * @param name
115
         * @param moduleId
116
         * @param packageName
117
         * @param author
118
         * @param description
119
         * @param version
120
         */
121
        public Module(String name, String moduleId, String packageName, String author, String description, String version,
122
                                  String configVersion) {
1✔
123
                this.name = name;
1✔
124
                this.moduleId = moduleId;
1✔
125
                this.packageName = packageName;
1✔
126
                this.author = author;
1✔
127
                this.description = description;
1✔
128
                this.version = version;
1✔
129
                this.configVersion = configVersion;
1✔
130
                log.debug("Creating module " + name);
1✔
131
        }
1✔
132
        
133
        @Override
134
        public boolean equals(Object obj) {
135
                if (obj != null && obj instanceof Module) {
1✔
136
                        Module mod = (Module) obj;
1✔
137
                        return getModuleId().equals(mod.getModuleId());
1✔
138
                }
139
                return false;
1✔
140
        }
141
        
142
        @Override
143
        public int hashCode() {
144
                return new HashCodeBuilder().append(getModuleId()).toHashCode();
1✔
145
        }
146
        
147
        /**
148
         * @return the moduleActivator
149
         */
150
        public ModuleActivator getModuleActivator() {
151
                try {
152
                        if (moduleActivator == null) {
1✔
153
                                ModuleClassLoader classLoader = ModuleFactory.getModuleClassLoader(this);
1✔
154
                                if (classLoader == null) {
1✔
155
                                        throw new ModuleException("The classloader is null", getModuleId());
×
156
                                }
157
                                
158
                                Class<?> c = classLoader.loadClass(getActivatorName());
1✔
159
                                Object o = c.newInstance();
1✔
160
                                if (ModuleActivator.class.isAssignableFrom(o.getClass())) {
1✔
161
                                        setModuleActivator((ModuleActivator) o);
1✔
162
                                }
163
                        }
164
                        
165
                }
166
                catch (ClassNotFoundException | NoClassDefFoundError e) {
×
167
                        
168
                        throw new ModuleException("Unable to load/find moduleActivator: '" + getActivatorName() + "'", name, e);
×
169
                }
170
                catch (IllegalAccessException e) {
×
171
                        throw new ModuleException("Unable to load/access moduleActivator: '" + getActivatorName() + "'", name, e);
×
172
                }
173
                catch (InstantiationException e) {
×
174
                        throw new ModuleException("Unable to load/instantiate moduleActivator: '" + getActivatorName() + "'", name, e);
×
175
                }
1✔
176

177
                return moduleActivator;
1✔
178
        }
179
        
180
        /**
181
         * @param moduleActivator the moduleActivator to set
182
         */
183
        public void setModuleActivator(ModuleActivator moduleActivator) {
184
                this.moduleActivator = moduleActivator;
1✔
185
        }
1✔
186
        
187
        /**
188
         * @return the activatorName
189
         */
190
        public String getActivatorName() {
191
                return activatorName;
1✔
192
        }
193
        
194
        /**
195
         * @param activatorName the activatorName to set
196
         */
197
        public void setActivatorName(String activatorName) {
198
                this.activatorName = activatorName;
1✔
199
        }
1✔
200
        
201
        /**
202
         * @return the author
203
         */
204
        public String getAuthor() {
205
                return author;
1✔
206
        }
207
        
208
        /**
209
         * @param author the author to set
210
         */
211
        public void setAuthor(String author) {
212
                this.author = author;
×
213
        }
×
214
        
215
        /**
216
         * @return the description
217
         */
218
        public String getDescription() {
219
                return description;
1✔
220
        }
221
        
222
        /**
223
         * @param description the description to set
224
         */
225
        public void setDescription(String description) {
226
                this.description = description;
×
227
        }
×
228
        
229
        /**
230
         * @return the name
231
         */
232
        public String getName() {
233
                return name;
1✔
234
        }
235
        
236
        /**
237
         * @param name the name to set
238
         */
239
        public void setName(String name) {
240
                this.name = name;
×
241
        }
×
242
        
243
        /**
244
         * @return the requireDatabaseVersion
245
         */
246
        public String getRequireDatabaseVersion() {
247
                return requireDatabaseVersion;
1✔
248
        }
249
        
250
        /**
251
         * @param requireDatabaseVersion the requireDatabaseVersion to set
252
         */
253
        public void setRequireDatabaseVersion(String requireDatabaseVersion) {
254
                this.requireDatabaseVersion = requireDatabaseVersion;
1✔
255
        }
1✔
256
        
257
        /**
258
         * This list of strings is just what is included in the config.xml file, the full package names:
259
         * e.g. org.openmrs.module.formentry
260
         *
261
         * @return the list of requiredModules
262
         */
263
        public List<String> getRequiredModules() {
264
                return requiredModulesMap == null ? null : new ArrayList<>(requiredModulesMap.keySet());
1✔
265
        }
266
        
267
        /**
268
         * Convenience method to get the version of this given module that is required
269
         *
270
         * @return the version of the given required module, or null if there are no version constraints
271
         * @since 1.5
272
         * <strong>Should</strong> return null if no required modules exist
273
         * <strong>Should</strong> return null if no required module by given name exists
274
         */
275
        public String getRequiredModuleVersion(String moduleName) {
276
                return requiredModulesMap == null ? null : requiredModulesMap.get(moduleName);
1✔
277
        }
278
        
279
        /**
280
         * This is a convenience method to set all the required modules without any version requirements
281
         *
282
         * @param requiredModules the requiredModules to set for this module
283
         * <strong>Should</strong> set modules when there is a null required modules map
284
         */
285
        public void setRequiredModules(List<String> requiredModules) {
286
                if (requiredModulesMap == null) {
1✔
287
                        requiredModulesMap = new HashMap<>();
1✔
288
                }
289
                
290
                for (String module : requiredModules) {
1✔
291
                        requiredModulesMap.put(module, null);
1✔
292
                }
1✔
293
        }
1✔
294
        
295
        /**
296
         * @param requiredModule the requiredModule to add for this module
297
         * @param version version requiredModule
298
         * <strong>Should</strong> add module to required modules map
299
         */
300
        public void addRequiredModule(String requiredModule, String version) {
301
                if (requiredModulesMap != null) {
1✔
302
                        requiredModulesMap.put(requiredModule, version);
1✔
303
                }
304
        }
1✔
305
        
306
        /**
307
         * @param requiredModulesMap <code>Map&lt;String,String&gt;</code> of the <code>requiredModule</code>s
308
         *            to set
309
         * @since 1.5
310
         */
311
        public void setRequiredModulesMap(Map<String, String> requiredModulesMap) {
312
                this.requiredModulesMap = requiredModulesMap;
1✔
313
        }
1✔
314
        
315
        /**
316
         * Get the modules that are required for this module. The keys in this map are the module
317
         * package names. The values in the map are the required version. If no specific version is
318
         * required, it will be null.
319
         *
320
         * @return a map from required module to the version that is required
321
         */
322
        public Map<String, String> getRequiredModulesMap() {
323
                return requiredModulesMap;
1✔
324
        }
325
        
326
        /**
327
         * Sets modules that must start after this module
328
         * @param startBeforeModulesMap the startedBefore modules to set
329
         */
330
        public void setStartBeforeModulesMap(Map<String, String> startBeforeModulesMap) {
331
                this.startBeforeModulesMap = startBeforeModulesMap;
1✔
332
        }
1✔
333
        
334
        /**
335
         * Gets modules which should start after this
336
         * @return map where key is module name and value is module version
337
         */
338
        public Map<String, String> getStartBeforeModulesMap() {
339
                return this.startBeforeModulesMap;
1✔
340
        }
341
        
342
        /**
343
         * Gets names of modules which should start after this
344
         * @since 1.11
345
         * @return list of module names or null
346
         */
347
        public List<String> getStartBeforeModules() {
348
                return this.startBeforeModulesMap == null ? null : new ArrayList<>(this.startBeforeModulesMap.keySet());
1✔
349
        }
350
        
351
        /**
352
         * Sets the modules that this module is aware of.
353
         *
354
         * @param awareOfModulesMap <code>Map&lt;String,String&gt;</code> of the
355
         *            <code>awareOfModulesMap</code>s to set
356
         * @since 1.9
357
         */
358
        public void setAwareOfModulesMap(Map<String, String> awareOfModulesMap) {
359
                this.awareOfModulesMap = awareOfModulesMap;
1✔
360
        }
1✔
361
        
362
        /**
363
         * This list of strings is just what is included in the config.xml file, the full package names:
364
         * e.g. org.openmrs.module.formentry, for the modules that this module is aware of.
365
         *
366
         * @since 1.9
367
         * @return the list of awareOfModules
368
         */
369
        public List<String> getAwareOfModules() {
370
                return awareOfModulesMap == null ? null : new ArrayList<>(awareOfModulesMap.keySet());
1✔
371
        }
372
        
373
        public String getAwareOfModuleVersion(String awareOfModule) {
374
                return awareOfModulesMap == null ? null : awareOfModulesMap.get(awareOfModule);
×
375
        }
376
        
377
        /**
378
         * @return the requireOpenmrsVersion
379
         */
380
        public String getRequireOpenmrsVersion() {
381
                return requireOpenmrsVersion;
1✔
382
        }
383
        
384
        /**
385
         * @param requireOpenmrsVersion the requireOpenmrsVersion to set
386
         */
387
        public void setRequireOpenmrsVersion(String requireOpenmrsVersion) {
388
                this.requireOpenmrsVersion = requireOpenmrsVersion;
1✔
389
        }
1✔
390
        
391
        /**
392
         * @return the module id
393
         */
394
        public String getModuleId() {
395
                return moduleId;
1✔
396
        }
397
        
398
        /**
399
         * @return the module id, with all . replaced with /
400
         */
401
        public String getModuleIdAsPath() {
402
                return moduleId == null ? null : moduleId.replace('.', '/');
1✔
403
        }
404
        
405
        /**
406
         * @param moduleId the module id to set
407
         */
408
        public void setModuleId(String moduleId) {
409
                this.moduleId = moduleId;
1✔
410
        }
1✔
411
        
412
        /**
413
         * @return the packageName
414
         */
415
        public String getPackageName() {
416
                return packageName;
1✔
417
        }
418
        
419
        /**
420
         * @param packageName the packageName to set
421
         */
422
        public void setPackageName(String packageName) {
423
                this.packageName = packageName;
×
424
        }
×
425
        
426
        /**
427
         * @return the version
428
         */
429
        public String getVersion() {
430
                return version;
1✔
431
        }
432
        
433
        /**
434
         * @param version the version to set
435
         */
436
        public void setVersion(String version) {
437
                this.version = version;
×
438
        }
×
439
        
440
        /**
441
         * @return the updateURL
442
         */
443
        public String getUpdateURL() {
444
                return updateURL;
1✔
445
        }
446
        
447
        /**
448
         * @param updateURL the updateURL to set
449
         */
450
        public void setUpdateURL(String updateURL) {
451
                this.updateURL = updateURL;
1✔
452
        }
1✔
453
        
454
        /**
455
         * @return the downloadURL
456
         */
457
        public String getDownloadURL() {
458
                return downloadURL;
×
459
        }
460
        
461
        /**
462
         * @param downloadURL the downloadURL to set
463
         */
464
        public void setDownloadURL(String downloadURL) {
465
                this.downloadURL = downloadURL;
×
466
        }
×
467
        
468
        /**
469
         * @return the updateVersion
470
         */
471
        public String getUpdateVersion() {
472
                return updateVersion;
×
473
        }
474
        
475
        /**
476
         * @param updateVersion the updateVersion to set
477
         */
478
        public void setUpdateVersion(String updateVersion) {
479
                this.updateVersion = updateVersion;
×
480
        }
×
481
        
482
        /**
483
         * Expands (i.e. creates instances of) {@code Extension}s defined by their class name in {@link #setExtensionNames(Map)}.
484
         * 
485
         * @return the extensions
486
         *
487
         * <strong>Should</strong> not expand extensionNames if extensionNames is null
488
         * <strong>Should</strong> not expand extensionNames if extensionNames is empty
489
         * <strong>Should</strong> not expand extensionNames if extensions matches extensionNames
490
         * <strong>Should</strong> expand extensionNames if extensions does not match extensionNames 
491
         */
492
        public List<Extension> getExtensions() {
493
                if (isNoNeedToExpand()) {
1✔
494
                        return extensions;
1✔
495
                }
496
                return expandExtensionNames();
1✔
497
        }
498
        
499
        /**
500
         * @param extensions the extensions to set
501
         */
502
        public void setExtensions(List<Extension> extensions) {
503
                this.extensions = extensions;
×
504
        }
×
505
        
506
        /**
507
         * A map of pointId to classname. The classname is expected to be a class that extends the
508
         * {@link Extension} object.
509
         * <br>
510
         * This map will be expanded into full Extension objects the first time {@link #getExtensions()}
511
         * is called.
512
         * <p>
513
         * The map is a direct representation of {@code extension} tags in a module's config.xml. For example
514
         * <pre>{@code
515
         * <extension>
516
         *     <point>org.openmrs.admin.list</point>
517
         *     <class>org.openmrs.module.reporting.web.extension.ManageAdminListExt</class>
518
         * </extension>
519
         * }
520
         * </pre>
521
         * </p>
522
         *
523
         * @param map from pointid to classname of an extension
524
         * @see ModuleFileParser
525
         */
526
        public void setExtensionNames(Map<String, String> map) {
527
                if (log.isDebugEnabled()) {
1✔
528
                        for (Map.Entry<String, String> entry : extensionNames.entrySet()) {
×
529
                                log.debug("Setting extension names: {} : {}", entry.getKey(), entry.getValue());
×
530
                        }
×
531
                }
532
                this.extensionNames = map;
1✔
533
        }
1✔
534

535
        private boolean isNoNeedToExpand() {
536
                if (extensionNames == null || extensionNames.isEmpty()) {
1✔
537
                        return true;
1✔
538
                }
539
                
540
                for (Extension ext : extensions) {
1✔
541
                        if (!extensionNames.get(ext.getPointId()).equals(ext.getClass().getName())) {
1✔
542
                                return false;
1✔
543
                        }
544
                }
1✔
545
                return extensions.size() == extensionNames.size();
1✔
546
        }
547
        
548
        /**
549
         * Expand the temporary extensionNames map of pointid-classname to full pointid-classobject. <br>
550
         * This has to be done after the fact because when the pointid-classnames are parsed, the
551
         * module's objects aren't fully realized yet and so not all classes can be loaded. <br>
552
         * <br>
553
         *
554
         * @return a list of full Extension objects
555
         */
556
        private List<Extension> expandExtensionNames() {
557
                ModuleClassLoader moduleClsLoader = ModuleFactory.getModuleClassLoader(this);
1✔
558
                if (moduleClsLoader == null) {
1✔
559
                        log.debug("Module class loader is not available, maybe the module {} is stopped/stopping", getName());
1✔
560
                        return extensions;
1✔
561
                }
562
                
563
                extensions.clear();
1✔
564
                for (Map.Entry<String, String> entry : extensionNames.entrySet()) {
1✔
565
                        String point = entry.getKey();
1✔
566
                        String className = entry.getValue();
1✔
567
                        log.debug(getModuleId() + ": Expanding extension name (point|class): {}|{}", point, className);
1✔
568
                        try {
569
                                Class<?> cls = moduleClsLoader.loadClass(className);
1✔
570
                                Extension ext = (Extension) cls.newInstance();
1✔
571
                                ext.setPointId(point);
1✔
572
                                ext.setModuleId(this.getModuleId());
1✔
573
                                extensions.add(ext);
1✔
574
                                log.debug(getModuleId() + ": Added extension: {}|{}", ext.getExtensionId(), ext.getClass());
1✔
575
                        }
576
                        catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoClassDefFoundError e) {
1✔
577
                                log.warn(getModuleId() + ": Unable to create instance of class defined for extension point: " + point, e);
1✔
578
                        }
1✔
579
                }
1✔
580
                return extensions;
1✔
581
        }
582
        
583
        /**
584
         * @return the advicePoints
585
         */
586
        public List<AdvicePoint> getAdvicePoints() {
587
                return advicePoints;
1✔
588
        }
589
        
590
        /**
591
         * @param advicePoints the advicePoints to set
592
         */
593
        public void setAdvicePoints(List<AdvicePoint> advicePoints) {
594
                this.advicePoints = advicePoints;
1✔
595
        }
1✔
596
        
597
        public File getFile() {
598
                return file;
1✔
599
        }
600
        
601
        public void setFile(File file) {
602
                this.file = file;
1✔
603
        }
1✔
604
        
605
        /**
606
         * Gets a mapping from locale to properties used by this module. The locales are represented as
607
         * a string containing language and country codes.
608
         *
609
         * @return mapping from locales to properties
610
         * @deprecated as of 2.0 because messages are automatically loaded from the classpath
611
         */
612
        @Deprecated
613
        public Map<String, Properties> getMessages() {
614
                return messages;
×
615
        }
616
        
617
        /**
618
         * Sets the map from locale to properties used by this module.
619
         *
620
         * @param messages map of locale to properties for that locale
621
         * @deprecated as of 2.0 because messages are automatically loaded from the classpath
622
         */
623
        @Deprecated
624
        public void setMessages(Map<String, Properties> messages) {
625
                this.messages = messages;
×
626
        }
×
627
        
628
        public List<GlobalProperty> getGlobalProperties() {
629
                return globalProperties;
1✔
630
        }
631
        
632
        public void setGlobalProperties(List<GlobalProperty> globalProperties) {
633
                this.globalProperties = globalProperties;
1✔
634
        }
1✔
635
        
636
        public List<Privilege> getPrivileges() {
637
                return privileges;
1✔
638
        }
639
        
640
        public void setPrivileges(List<Privilege> privileges) {
641
                this.privileges = privileges;
1✔
642
        }
1✔
643
        
644
        public Document getConfig() {
645
                return config;
×
646
        }
647
        
648
        public void setConfig(Document config) {
649
                this.config = config;
1✔
650
        }
1✔
651

652
        /**
653
         * @since 2.7.0
654
         */
655
        public String getConfigVersion() {
656
                return configVersion;
1✔
657
        }
658

659
        /**
660
         * @since 2.7.0
661
         */
662
        public void setConfigVersion(String configVersion) {
663
                this.configVersion = configVersion;
×
664
        }
×
665

666
        public Document getSqldiff() {
667
                return sqldiff;
×
668
        }
669
        
670
        public void setSqldiff(Document sqldiff) {
671
                this.sqldiff = sqldiff;
×
672
        }
×
673
        
674
        public List<String> getMappingFiles() {
675
                return mappingFiles;
1✔
676
        }
677
        
678
        public void setMappingFiles(List<String> mappingFiles) {
679
                this.mappingFiles = mappingFiles;
1✔
680
        }
1✔
681
        
682
        /**
683
         * Packages to scan for classes with JPA annotated classes.
684
         * @return the set of packages to scan
685
         * @since 1.9.2, 1.10
686
         */
687
        public Set<String> getPackagesWithMappedClasses() {
688
                return packagesWithMappedClasses;
1✔
689
        }
690
        
691
        /**
692
         * @param packagesToScan
693
         * @see #getPackagesWithMappedClasses()
694
         * @since 1.9.2, 1.10
695
         */
696
        public void setPackagesWithMappedClasses(Set<String> packagesToScan) {
697
                this.packagesWithMappedClasses = packagesToScan;
1✔
698
        }
1✔
699
        
700
        /**
701
         * This property is set by the module owner to tell OpenMRS that once it is installed, it must
702
         * always startup. This is intended for modules with system-critical monitoring or security
703
         * checks that should always be in place.
704
         *
705
         * @return true if this module has said that it should always start up
706
         */
707
        public boolean isMandatory() {
708
                return mandatory;
1✔
709
        }
710
        
711
        public void setMandatory(boolean mandatory) {
712
                this.mandatory = mandatory;
1✔
713
        }
1✔
714
        
715
        public boolean isStarted() {
716
                return ModuleFactory.isModuleStarted(this);
1✔
717
        }
718
        
719
        /**
720
         * @param e string to set as startup error message
721
         * <strong>Should</strong> throw exception when message is null
722
         */
723
        public void setStartupErrorMessage(String e) {
724
                if (e == null) {
1✔
725
                        throw new ModuleException("Startup error message cannot be null", this.getModuleId());
1✔
726
                }
727
                
UNCOV
728
                this.startupErrorMessage = e;
×
UNCOV
729
        }
×
730
        
731
        /**
732
         * Add the given exceptionMessage and throwable as the startup error for this module. This
733
         * method loops over the stacktrace and adds the detailed message
734
         *
735
         * @param exceptionMessage optional. the default message to show on the first line of the error
736
         *            message
737
         * @param t throwable stacktrace to include in the error message
738
         *
739
         * <strong>Should</strong> throw exception when throwable is null
740
         * <strong>Should</strong> set StartupErrorMessage when exceptionMessage is null
741
         * <strong>Should</strong> append throwable's message to exceptionMessage
742
         */
743
        public void setStartupErrorMessage(String exceptionMessage, Throwable t) {
744
                if (t == null) {
1✔
745
                        throw new ModuleException("Startup error value cannot be null", this.getModuleId());
1✔
746
                }
747
                
748
                StringBuilder sb = new StringBuilder();
1✔
749
                
750
                // if exceptionMessage is not null, append it
751
                if (exceptionMessage != null) {
1✔
752
                        sb.append(exceptionMessage);
1✔
753
                        sb.append("\n");
1✔
754
                }
755
                
756
                sb.append(t.getMessage());
1✔
757
                sb.append("\n");
1✔
758
                
759
                this.startupErrorMessage = sb.toString();
1✔
760
        }
1✔
761
        
762
        public String getStartupErrorMessage() {
763
                return startupErrorMessage;
1✔
764
        }
765
        
766
        public Boolean hasStartupError() {
767
                return (this.startupErrorMessage != null);
1✔
768
        }
769
        
770
        public void clearStartupError() {
771
                this.startupErrorMessage = null;
1✔
772
        }
1✔
773
        
774
        @Override
775
        public String toString() {
776
                if (moduleId == null) {
1✔
777
                        return super.toString();
×
778
                }
779
                
780
                return moduleId;
1✔
781
        }
782

783
        /*
784
         * <strong>Should</strong> dispose all classInstances, not AdvicePoints
785
         */        
786
        public void disposeAdvicePointsClassInstance() {
787
                if (advicePoints == null) {
1✔
788
                        return;
1✔
789
                }
790
                
791
                for (AdvicePoint advicePoint : advicePoints) {
1✔
792
                        advicePoint.disposeClassInstance();
1✔
793
                }
1✔
794
        }
1✔
795
        
796
        public List<ModuleConditionalResource> getConditionalResources() {
797
                return conditionalResources;
1✔
798
        }
799
        
800
        public void setConditionalResources(List<ModuleConditionalResource> conditionalResources) {
801
                this.conditionalResources = conditionalResources;
1✔
802
        }
1✔
803

804
}
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

© 2026 Coveralls, Inc