Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/sourcetools/objectmodel/com/ibm/j9tools/om/ObjectFactory.java
6004 views
1
/*******************************************************************************
2
* Copyright (c) 2007, 2019 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
package com.ibm.j9tools.om;
23
24
import java.io.File;
25
import java.io.IOException;
26
import java.io.InputStream;
27
import java.util.Collection;
28
import java.util.Collections;
29
import java.util.HashMap;
30
import java.util.HashSet;
31
import java.util.Map;
32
import java.util.Set;
33
import java.util.TreeMap;
34
import java.util.TreeSet;
35
36
import com.ibm.j9tools.om.io.BuildInfoParser;
37
import com.ibm.j9tools.om.io.BuildSpecParser;
38
import com.ibm.j9tools.om.io.FeatureParser;
39
import com.ibm.j9tools.om.io.FlagDefinitionParser;
40
41
/**
42
* The ObjectFactory provides a convenient way of turning files into object model classes.
43
*
44
* @author Gabriel Castro
45
* @author Han Xu
46
*/
47
public class ObjectFactory {
48
/** The configuration directory that will be scanned for flag definitions and feature references. */
49
private final ConfigDirectory configDirectory;
50
51
private BuildInfo buildInfoCache;
52
private FlagDefinitions flagDefinitionsCache;
53
private Map<String, FeatureDefinition> featureDefinitionsCache;
54
private Map<String, BuildSpec> buildSpecCache;
55
56
private Map<String, BuildSpec> invalidBuildSpecs;
57
private Map<String, FeatureDefinition> invalidFeatureDefinitions;
58
59
private final Map<String, Throwable> errors = new HashMap<String, Throwable>();
60
61
/**
62
* Creates a new ObjectFactory which will load from the specified <code>configDirectory</code>.
63
*
64
* @param configDirectory The directory from which resources will be loaded.
65
*/
66
public ObjectFactory(ConfigDirectory configDirectory) {
67
this.configDirectory = configDirectory;
68
69
flushCaches();
70
}
71
72
/**
73
* Flush all cached values.
74
*/
75
public void flushCaches() {
76
buildInfoCache = null;
77
flagDefinitionsCache = null;
78
featureDefinitionsCache = new HashMap<String, FeatureDefinition>();
79
buildSpecCache = new HashMap<String, BuildSpec>();
80
invalidBuildSpecs = new HashMap<String, BuildSpec>();
81
invalidFeatureDefinitions = new HashMap<String, FeatureDefinition>();
82
}
83
84
/**
85
* Retrieves this {@link ObjectFactory}'s config directory.
86
*
87
* @return the config directory
88
*/
89
public ConfigDirectory getConfigDirectory() {
90
return configDirectory;
91
}
92
93
/**
94
* Sets this {@link ObjectFactory}'s flag definitions.
95
*
96
* @param defs the new flag definitions
97
*/
98
public void setFlagDefinitions(FlagDefinitions defs) {
99
flagDefinitionsCache = (defs != null) ? defs : new FlagDefinitions();
100
flagDefinitionsCache.setRuntime(buildInfoCache.getRuntime());
101
102
Collection<IFlagContainer> flagContainers = new HashSet<IFlagContainer>();
103
104
flagContainers.addAll(featureDefinitionsCache.values());
105
flagContainers.addAll(invalidFeatureDefinitions.values());
106
flagContainers.addAll(buildSpecCache.values());
107
flagContainers.addAll(invalidBuildSpecs.values());
108
109
resetFlagDefinitions(flagContainers);
110
}
111
112
private void resetFlagDefinitions(Collection<IFlagContainer> containers) {
113
for (IFlagContainer container : containers) {
114
for (Flag flag : container.getLocalFlags().values()) {
115
if (flagDefinitionsCache.contains(flag.getId())) {
116
flag.setDefinition(flagDefinitionsCache.getFlagDefinition(flag.getId()));
117
} else {
118
flag.removeDefinition();
119
}
120
}
121
}
122
}
123
124
/**
125
* Retrieves all the flag definitions for this <code>ObjectFactory</code>.
126
*
127
* @return the flag definitions
128
*/
129
public FlagDefinitions getFlagDefinitions() {
130
return flagDefinitionsCache;
131
}
132
133
/**
134
* Sets the cached build info.
135
*
136
* @param buildInfo the build info to be cached
137
*/
138
public void setBuildInfo(BuildInfo buildInfo) {
139
buildInfoCache = buildInfo;
140
}
141
142
/**
143
* Retrieves the cached build info.
144
*
145
* @return The newly loaded build information.
146
*/
147
public BuildInfo getBuildInfo() {
148
return buildInfoCache;
149
}
150
151
/**
152
* Adds the {@link BuildSpec} to the valid build spec cache. If a {@link BuildSpec} with the same ID
153
* already exists in the cache it is overwritten.
154
*
155
* @param buildSpec the build spec to be added
156
*/
157
public void addBuildSpec(BuildSpec buildSpec) {
158
if (invalidBuildSpecs.containsKey(buildSpec.getId())) {
159
// Remove any errors associated with the invalid spec before removing it
160
errors.remove("buildspec:" + buildSpec.getId()); //$NON-NLS-1$
161
invalidBuildSpecs.remove(buildSpec.getId());
162
}
163
164
buildSpec.setRuntime(buildInfoCache.getRuntime());
165
buildSpecCache.put(buildSpec.getId(), buildSpec);
166
}
167
168
/**
169
* Adds the {@link BuildSpec} in the given {@link InvalidBuildSpecException} to the invalid build
170
* spec cache. If a {@link BuildSpec} with the same ID already exists in the cache it is overwritten.
171
*
172
* @param e the exception containing the invalid build spec to be added
173
*/
174
public void addInvalidBuildSpec(InvalidBuildSpecException e) {
175
if (e.getObject() != null) {
176
errors.put("buildspec:" + e.getObject().getId(), e); //$NON-NLS-1$
177
invalidBuildSpecs.put(e.getObject().getId(), e.getObject());
178
}
179
}
180
181
/**
182
* Removes the given <code>BuildSpec</code> from the valid build spec cache.
183
*
184
* @param buildSpecId the ID of the build spec to be removed
185
* @return the build spec removed
186
*/
187
public BuildSpec removeBuildSpec(String buildSpecId) {
188
return buildSpecCache.remove(buildSpecId);
189
}
190
191
/**
192
* Removes the given {@link BuildSpec} from the invalid build spec cache.
193
*
194
* @param buildSpecId the ID of the build spec to be removed
195
* @return the build spec removed
196
*/
197
public BuildSpec removeInvalidBuildSpec(String buildSpecId) {
198
// Remove any errors associated with the invalid spec before removing it
199
errors.remove("buildspec:" + buildSpecId); //$NON-NLS-1$
200
return invalidBuildSpecs.remove(buildSpecId);
201
}
202
203
/**
204
* Adds the given {@link FeatureDefinition} to the valid feature cache. If a {@link FeatureDefinition}
205
* with the same ID already exists in the cache it is overwritten. Adding a feature definition
206
* will also link it to any {@link BuildSpec} that includes a {@link Feature} of the same ID.
207
*
208
* @param featureDefinition the feature definition to be added
209
*/
210
public void addFeatureDefinition(FeatureDefinition featureDefinition) {
211
for (BuildSpec buildSpec : buildSpecCache.values()) {
212
if (buildSpec.hasFeature(featureDefinition.getId())) {
213
buildSpec.getFeature(featureDefinition.getId()).setDefinition(featureDefinition);
214
}
215
}
216
217
for (BuildSpec buildSpec : invalidBuildSpecs.values()) {
218
if (buildSpec.hasFeature(featureDefinition.getId())) {
219
buildSpec.getFeature(featureDefinition.getId()).setDefinition(featureDefinition);
220
}
221
}
222
223
if (invalidFeatureDefinitions.containsKey(featureDefinition.getId())) {
224
// Remove any errors associated with the invalid feature definition before removing it
225
errors.remove("feature:" + featureDefinition.getId()); //$NON-NLS-1$
226
invalidFeatureDefinitions.remove(featureDefinition.getId());
227
}
228
229
featureDefinition.setRuntime(buildInfoCache.getRuntime());
230
featureDefinitionsCache.put(featureDefinition.getId(), featureDefinition);
231
}
232
233
/**Adds the {@link FeatureDefinition} in the given {@link InvalidFeatureDefinitionException} to
234
* the invalid feature cache. If a {@link FeatureDefinition} with the same ID already exists in
235
* the cache it is overwritten.
236
*
237
* @param e the exception containing the invalid feature definition to be added
238
*/
239
public void addInvalidFeatureDefinition(InvalidFeatureDefinitionException e) {
240
if (e.getObject() != null) {
241
errors.put("feature:" + e.getObject().getId(), e); //$NON-NLS-1$
242
invalidFeatureDefinitions.put(e.getObject().getId(), e.getObject());
243
}
244
}
245
246
/**
247
* Removes the {@link FeatureDefinition} with the given ID from the valid feature cache. This also removes
248
* any links to this {@link FeatureDefinition} from all {@link BuildSpec}s including it.
249
*
250
* @param featureId the ID of the feature definition to be removed
251
* @return the removed feature
252
*/
253
public FeatureDefinition removeFeatureDefinition(String featureId) {
254
for (BuildSpec buildSpec : buildSpecCache.values()) {
255
if (buildSpec.hasFeature(featureId)) {
256
buildSpec.getFeature(featureId).removeDefinition();
257
}
258
}
259
260
for (BuildSpec buildSpec : invalidBuildSpecs.values()) {
261
if (buildSpec.hasFeature(featureId)) {
262
buildSpec.getFeature(featureId).removeDefinition();
263
}
264
}
265
266
return featureDefinitionsCache.remove(featureId);
267
}
268
269
/**
270
* Removes the {@link FeatureDefinition} with the given ID from the invalid feature cache.
271
*
272
* @param featureId the ID of the feature definition to be removed
273
* @return the removed feature
274
*/
275
public FeatureDefinition removeInvalidFeatureDefinition(String featureId) {
276
// Remove any errors associated with the invalid feature definition before removing it
277
errors.remove("feature:" + featureId); //$NON-NLS-1$
278
return invalidFeatureDefinitions.remove(featureId);
279
}
280
281
/**
282
* Loads the {@link FlagDefinitions} found in the given {@link File}.
283
*
284
* @param file the file containing flag definitions
285
* @return the parsed flag definitions
286
*
287
* @throws InvalidFlagDefinitionsException thrown if errors are found while parsing the flag definitions file
288
*/
289
public FlagDefinitions loadFlagDefinitions(File file) throws InvalidFlagDefinitionsException {
290
FlagDefinitionParser parser = new FlagDefinitionParser();
291
FlagDefinitions defs = null;
292
293
try {
294
defs = parser.parse(file);
295
} catch (IOException e) {
296
throw new InvalidFlagDefinitionsException(e, "flags"); //$NON-NLS-1$
297
}
298
299
try {
300
defs.verify();
301
} catch (InvalidFlagDefinitionsException e) {
302
throw new InvalidFlagDefinitionsException(e.getErrors(), defs);
303
}
304
305
defs.setRuntime(buildInfoCache.getRuntime());
306
307
return defs;
308
}
309
310
/**
311
* Loads the {@link FlagDefinitions} found in the given {@link File}.
312
*
313
* @param inputStream the input stream containing flag definitions
314
* @return the parsed flag definitions
315
*
316
* @throws InvalidFlagDefinitionsException thrown if errors are found while parsing the flag definitions input stream
317
*/
318
public FlagDefinitions loadFlagDefinitions(InputStream inputStream) throws InvalidFlagDefinitionsException {
319
FlagDefinitionParser parser = new FlagDefinitionParser();
320
FlagDefinitions defs = null;
321
322
try {
323
defs = parser.parse(inputStream);
324
} catch (IOException e) {
325
throw new InvalidFlagDefinitionsException(e, "flags"); //$NON-NLS-1$
326
}
327
328
try {
329
defs.verify();
330
} catch (InvalidFlagDefinitionsException e) {
331
throw new InvalidFlagDefinitionsException(e.getErrors(), defs);
332
}
333
334
defs.setRuntime(buildInfoCache.getRuntime());
335
336
return defs;
337
}
338
339
/**
340
* Loads the {@link BuildInfo} found in the given {@link File}.
341
*
342
* @param file the file containing the build info
343
* @return the parsed build info
344
*
345
* @throws InvalidBuildInfoException thrown if errors are found while parsing the build info file
346
*/
347
public BuildInfo loadBuildInfo(File file) throws InvalidBuildInfoException {
348
BuildInfo buildInfo;
349
350
try {
351
BuildInfoParser parser = new BuildInfoParser();
352
buildInfo = parser.parse(file);
353
} catch (IOException e) {
354
throw new InvalidBuildInfoException(e, "buildInfo"); //$NON-NLS-1$
355
}
356
357
return buildInfo;
358
}
359
360
/**
361
* Loads the {@link BuildInfo} found in the given {@link InputStream}.
362
*
363
* @param inputStream the input stream containing the build info
364
* @return the parsed build info
365
*
366
* @throws InvalidBuildInfoException thrown if errors are found while parsing the build info input stream
367
*/
368
public BuildInfo loadBuildInfo(InputStream inputStream) throws InvalidBuildInfoException {
369
BuildInfo buildInfo;
370
371
try {
372
BuildInfoParser parser = new BuildInfoParser();
373
buildInfo = parser.parse(inputStream);
374
} catch (IOException e) {
375
throw new InvalidBuildInfoException(e, "buildInfo"); //$NON-NLS-1$
376
}
377
378
return buildInfo;
379
}
380
381
/**
382
* Loads the {@link BuildSpec} found in the given {@link File}.
383
*
384
* @param file the spec file.
385
* @return the parsed build spec.
386
*
387
* @throws InvalidBuildSpecException thrown if errors are found while parsing the build spec file
388
*/
389
public BuildSpec loadBuildSpec(File file) throws InvalidBuildSpecException {
390
BuildSpecParser parser = new BuildSpecParser();
391
BuildSpec buildSpec = null;
392
393
try {
394
buildSpec = parser.parse(file, flagDefinitionsCache, featureDefinitionsCache);
395
} catch (IOException e) {
396
throw new InvalidBuildSpecException(e, file.getName().substring(0, file.getName().length() - ConfigDirectory.BUILD_SPEC_FILE_EXTENSION.length()));
397
}
398
399
try {
400
buildSpec.verify(flagDefinitionsCache, buildInfoCache);
401
} catch (InvalidBuildSpecException e) {
402
buildSpec = e.getObject();
403
String buildSpecId = (buildSpec == null) ? e.getObjectId() : buildSpec.getIdFromFile();
404
errors.put("buildspec:" + buildSpecId, e); //$NON-NLS-1$
405
406
if (buildSpec != null) {
407
invalidBuildSpecs.put(buildSpec.getIdFromFile(), buildSpec);
408
}
409
410
throw e;
411
}
412
413
buildSpec.setRuntime(buildInfoCache.getRuntime());
414
415
return buildSpec;
416
}
417
418
/**
419
* Loads the {@link BuildSpec} found in the given {@link InputStream}.
420
*
421
* @param inputStream the build spec input stream
422
* @return the newly loaded build spec.
423
*
424
* @throws InvalidBuildSpecException thrown if errors are found while parsing the build spec input stream
425
*/
426
public BuildSpec loadBuildSpec(InputStream inputStream, String objectId) throws InvalidBuildSpecException {
427
BuildSpecParser parser = new BuildSpecParser();
428
BuildSpec buildSpec = null;
429
430
try {
431
buildSpec = parser.parse(inputStream, objectId, flagDefinitionsCache, featureDefinitionsCache);
432
} catch (IOException e) {
433
throw new InvalidBuildSpecException(e, objectId);
434
}
435
436
try {
437
buildSpec.verify(flagDefinitionsCache, buildInfoCache);
438
} catch (InvalidBuildSpecException e) {
439
buildSpec = e.getObject();
440
String buildSpecId = (buildSpec == null) ? e.getObjectId() : buildSpec.getIdFromFile();
441
errors.put("buildspec:" + buildSpecId, e); //$NON-NLS-1$
442
443
if (buildSpec != null) {
444
invalidBuildSpecs.put(buildSpec.getIdFromFile(), buildSpec);
445
}
446
447
throw e;
448
}
449
450
buildSpec.setRuntime(buildInfoCache.getRuntime());
451
452
return buildSpec;
453
}
454
455
/**
456
* Loads the {@link FeatureDefinition} found in the given {@link File}.
457
*
458
* @param file the feature definition file
459
* @return the newly loaded feature definition
460
*
461
* @throws InvalidFeatureDefinitionException thrown if errors are found while parsing the feature definition file
462
*/
463
public FeatureDefinition loadFeatureDefinition(File file) throws InvalidFeatureDefinitionException {
464
FeatureParser parser = new FeatureParser();
465
FeatureDefinition featureDefinition = null;
466
467
try {
468
featureDefinition = parser.parse(file, flagDefinitionsCache);
469
} catch (IOException e) {
470
throw new InvalidFeatureDefinitionException(e, file.getName().substring(0, file.getName().length() - ConfigDirectory.FEATURE_FILE_EXTENSION.length()));
471
}
472
473
try {
474
if (buildInfoCache == null) {
475
featureDefinition.verify(flagDefinitionsCache, new HashSet<String>());
476
} else {
477
featureDefinition.verify(flagDefinitionsCache, buildInfoCache.getSources());
478
}
479
} catch (InvalidFeatureDefinitionException e) {
480
featureDefinition = e.getObject();
481
String featureDefinitionId = (featureDefinition == null) ? e.getObjectId() : featureDefinition.getId();
482
errors.put("feature:" + featureDefinitionId, e); //$NON-NLS-1$
483
484
if (featureDefinition != null) {
485
invalidFeatureDefinitions.put(featureDefinition.getId(), featureDefinition);
486
}
487
488
throw e;
489
}
490
491
featureDefinition.setRuntime(buildInfoCache.getRuntime());
492
493
return featureDefinition;
494
}
495
496
/**
497
* Loads the {@link FeatureDefinition} found in the given {@link InputStream}.
498
*
499
* @param inputStream the feature definition input stream
500
* @return the newly loaded feature definition
501
*
502
* @throws InvalidFeatureDefinitionException thrown if errors are found while parsing the feature definition input stream
503
*/
504
public FeatureDefinition loadFeatureDefinition(InputStream inputStream, String objectId) throws InvalidFeatureDefinitionException {
505
FeatureParser parser = new FeatureParser();
506
FeatureDefinition featureDefinition = null;
507
508
try {
509
featureDefinition = parser.parse(inputStream, objectId, flagDefinitionsCache);
510
} catch (IOException e) {
511
throw new InvalidFeatureDefinitionException(e, objectId);
512
}
513
514
try {
515
if (buildInfoCache == null) {
516
featureDefinition.verify(flagDefinitionsCache, new HashSet<String>());
517
} else {
518
featureDefinition.verify(flagDefinitionsCache, buildInfoCache.getSources());
519
}
520
} catch (InvalidFeatureDefinitionException e) {
521
featureDefinition = e.getObject();
522
String featureDefinitionId = (featureDefinition == null) ? e.getObjectId() : featureDefinition.getId();
523
errors.put("feature:" + featureDefinitionId, e); //$NON-NLS-1$
524
525
if (featureDefinition != null) {
526
invalidFeatureDefinitions.put(featureDefinition.getId(), featureDefinition);
527
}
528
529
throw e;
530
}
531
532
featureDefinition.setRuntime(buildInfoCache.getRuntime());
533
534
return featureDefinition;
535
}
536
537
/**
538
* Retrieves the {@link FeatureDefinition} with the given <code>featureId</code> from the cache.
539
*
540
* @param featureId the ID of the desired Feature
541
* @return the Feature requested
542
*
543
* @throws InvalidFeatureDefinitionException if the feature definition contains errors
544
*/
545
public FeatureDefinition getFeature(String featureId) throws InvalidFeatureDefinitionException {
546
if (invalidFeatureDefinitions.containsKey(featureId)) {
547
throw (InvalidFeatureDefinitionException) errors.get("feature:" + featureId); //$NON-NLS-1$
548
}
549
550
return featureDefinitionsCache.get(featureId);
551
}
552
553
public BuildSpec getDefaultActiveSpec() {
554
int highestPriority = -1;
555
BuildSpec defaultActiveSpec = null;
556
557
for (BuildSpec spec : buildSpecCache.values()) {
558
if (spec.getPriority() > highestPriority) {
559
highestPriority = spec.getPriority();
560
defaultActiveSpec = spec;
561
}
562
}
563
564
return defaultActiveSpec;
565
}
566
567
/**
568
* Retrieves the {@link BuildSpec} with the given <code>buildSpecId</code> from the cache.
569
*
570
* @param buildSpecId the ID of the desired BuildSpec
571
* @return the BuildSpec requested
572
*
573
* @throws InvalidBuildSpecException
574
*/
575
public BuildSpec getBuildSpec(String buildSpecId) throws InvalidBuildSpecException {
576
if (invalidBuildSpecs.containsKey(buildSpecId)) {
577
throw (InvalidBuildSpecException) errors.get("buildspec:" + buildSpecId); //$NON-NLS-1$
578
}
579
580
return buildSpecCache.get(buildSpecId);
581
}
582
583
/**
584
* Retrieves a list of all the valid {@link BuildSpec}s in the factory's config directory.
585
*
586
* @return a list of all the valid build specs
587
*/
588
public Collection<BuildSpec> getBuildSpecs() {
589
return buildSpecCache.values();
590
}
591
592
public Collection<BuildSpec> getAllBuildSpecs() {
593
Map<String, BuildSpec> temp = new TreeMap<String, BuildSpec>();
594
temp.putAll(buildSpecCache);
595
596
for (String specID : invalidBuildSpecs.keySet()) {
597
if (invalidBuildSpecs.get(specID) != null) {
598
temp.put(specID, invalidBuildSpecs.get(specID));
599
}
600
}
601
602
return temp.values();
603
}
604
605
/**
606
* Retrieves the list of all valid {@link BuildSpec} IDs in this factory's config directory.
607
*
608
* @return a list of all valid build spec IDs
609
*/
610
public Set<String> getBuildSpecIds() {
611
return buildSpecCache.keySet();
612
}
613
614
/**
615
* Retrieves the map of all valid {@link BuildSpec}s in this factory's config directory.
616
*
617
* @return a map of all valid build specs
618
*/
619
public Map<String, BuildSpec> getBuildSpecsMap() {
620
return Collections.unmodifiableMap(buildSpecCache);
621
}
622
623
/**
624
* Returns a <code>Set</code> containing all the OS types for the specs in this <code>ObjectFactory</code>.
625
*
626
* @return the OS types for all the build specs
627
*/
628
public Set<String> getBuildSpecOSes() {
629
Set<String> buildSpecOSes = new TreeSet<String>();
630
631
for (BuildSpec spec : buildSpecCache.values()) {
632
buildSpecOSes.add(spec.getOs());
633
}
634
635
return buildSpecOSes;
636
}
637
638
/**
639
* Retrieves the valid build specs for the given OS.
640
*
641
* @param os the OS for which to return build specs
642
* @return the build specs of the given OS
643
*/
644
public Set<BuildSpec> getBuildSpecsByOS(String os) {
645
Set<BuildSpec> buildSpecs = new TreeSet<BuildSpec>();
646
647
for (BuildSpec buildSpec : buildSpecCache.values()) {
648
if (os.equals(buildSpec.getOs())) {
649
buildSpecs.add(buildSpec);
650
}
651
}
652
653
return buildSpecs;
654
}
655
656
/**
657
* Retrieves the list of J9 Specifications that have the given feature. Returns an empty set
658
* if the feature ID is null or an empty string.
659
*
660
* @param featureID the ID of the feature to be searched for
661
* @return the set of specs with the given feature, or an empty set if none exist or the
662
* feature ID is not valid
663
*/
664
public Set<BuildSpec> getBuildSpecsByFeature(String featureID) {
665
Set<BuildSpec> buildSpecs = new TreeSet<BuildSpec>();
666
667
if (featureID != null && featureID.length() > 0) {
668
for (BuildSpec spec : buildSpecCache.values()) {
669
if (spec.getFeatures().keySet().contains(featureID)) {
670
buildSpecs.add(spec);
671
}
672
}
673
}
674
675
return buildSpecs;
676
}
677
678
/**
679
* Retrieves the list of J9 Specification IDs that have the given feature. Returns an empty set
680
* if the feature ID is null or an empty string.
681
*
682
* @param featureID the ID of the feature to be searched for
683
* @return the set of spec IDs with the given feature, or an empty set if none exist or the
684
* feature ID is not valid
685
*/
686
public Set<String> getBuildSpecIDsByFeature(String featureID) {
687
Set<String> buildSpecs = new TreeSet<String>();
688
689
if (featureID != null && featureID.length() > 0) {
690
for (BuildSpec spec : buildSpecCache.values()) {
691
if (spec.getFeatures().keySet().contains(featureID)) {
692
buildSpecs.add(spec.getId());
693
}
694
}
695
}
696
697
return buildSpecs;
698
}
699
700
/**
701
* Retrieves the valid {@link FeatureDefinition}s in the factory's config directory.
702
*
703
* @return the valid feature definitions
704
*/
705
public Collection<FeatureDefinition> getFeatureDefinitions() {
706
return featureDefinitionsCache.values();
707
}
708
709
/**
710
* Retrieves the set of valid {@link FeatureDefinition} IDs the factory's config directory.
711
*
712
* @return the valid feature definition IDs
713
*/
714
public Set<String> getFeatureDefinitionIds() {
715
return featureDefinitionsCache.keySet();
716
}
717
718
/**
719
* Retrieves the map of valid {@link FeatureDefinition}s the factory's config directory.
720
*
721
* @return the valid feature definitions
722
*/
723
public Map<String, FeatureDefinition> getFeatureDefinitionsMap() {
724
return Collections.unmodifiableMap(featureDefinitionsCache);
725
}
726
727
/**
728
* Loads a runtime's build-info, flag definitions as well as all the valid build specs and features
729
* contained in this <code>ObjectFactory</code>'s config directory.
730
*
731
* Errors found when loading the build-info and flag definitions are considered fatal and will result
732
* on an {@link InvalidFactoryException} being thrown (even if errors are delayed). Errors found
733
* when loading features or build specs will result in that element not being loaded into the factory.
734
*
735
* @param delayErrors delay throwing exceptions unless error is critical (build-info or flags invalid)
736
*
737
* @throws InvalidFactoryException thrown if errors are found when initializing factory elements
738
*/
739
public void initialize(boolean delayErrors) throws InvalidFactoryException {
740
boolean notDelayable = false;
741
742
// Load basic information
743
try {
744
buildInfoCache = loadBuildInfo(configDirectory.getBuildInfoFile());
745
} catch (InvalidBuildInfoException e) {
746
buildInfoCache = e.getObject();
747
errors.put("buildInfo", e); //$NON-NLS-1$
748
notDelayable = true;
749
}
750
751
// Can't parse much more if we don't even have a partial build-info
752
if (buildInfoCache != null) {
753
// Load flag definitions
754
try {
755
flagDefinitionsCache = loadFlagDefinitions(configDirectory.getFlagDefinitionsFile());
756
} catch (InvalidFlagDefinitionsException e) {
757
flagDefinitionsCache = (e.getObject() == null) ? new FlagDefinitions() : e.getObject();
758
errors.put("flags", e); //$NON-NLS-1$
759
notDelayable = true;
760
}
761
762
// Load features
763
for (File file : configDirectory.getFeatureFiles()) {
764
FeatureDefinition featureDefinition;
765
766
try {
767
featureDefinition = loadFeatureDefinition(file);
768
featureDefinitionsCache.put(featureDefinition.getId(), featureDefinition);
769
} catch (InvalidFeatureDefinitionException e) {
770
errors.put("feature:" + e.getObjectId(), e); //$NON-NLS-1$
771
}
772
}
773
774
// Load build specs
775
for (File file : configDirectory.getBuildSpecFiles()) {
776
BuildSpec buildSpec;
777
778
try {
779
buildSpec = loadBuildSpec(file);
780
buildSpecCache.put(buildSpec.getId(), buildSpec);
781
} catch (InvalidBuildSpecException e) {
782
errors.put("buildspec:" + e.getObjectId(), e); //$NON-NLS-1$
783
}
784
}
785
}
786
787
if (errors.size() > 0 && (!delayErrors || notDelayable)) {
788
throw new InvalidFactoryException(errors.values(), this);
789
}
790
}
791
792
/**
793
* Initializes the factory without delaying errors found.
794
*
795
* @see #initialize(boolean)
796
*
797
* @throws InvalidFactoryException thrown if errors are found when initializing factory elements
798
*/
799
public void initialize() throws InvalidFactoryException {
800
initialize(false);
801
}
802
803
/**
804
* Verifies the flag definitions, features, and build specs for validity. This is to be used
805
* when modifying elements on a object factory that has already been initialized.
806
*
807
* @throws InvalidFactoryException thrown if errors are found when verifying factory elements
808
*/
809
public void verify() throws InvalidFactoryException {
810
Set<Throwable> exceptions = new HashSet<Throwable>();
811
812
Set<BuildSpec> brokenSpecs = new HashSet<BuildSpec>();
813
Set<BuildSpec> cleanSpecs = new HashSet<BuildSpec>();
814
Set<FeatureDefinition> brokenFeatures = new HashSet<FeatureDefinition>();
815
Set<FeatureDefinition> cleanFeatures = new HashSet<FeatureDefinition>();
816
817
// Verify flag definitions
818
try {
819
flagDefinitionsCache.verify();
820
} catch (InvalidFlagDefinitionsException e) {
821
exceptions.add(e);
822
}
823
824
// Check features that were broken
825
// If they have been fixed then add them back
826
for (FeatureDefinition featureDefinition : invalidFeatureDefinitions.values()) {
827
try {
828
if (buildInfoCache == null) {
829
featureDefinition.verify(flagDefinitionsCache, new HashSet<String>());
830
} else {
831
featureDefinition.verify(flagDefinitionsCache, buildInfoCache.getSources());
832
}
833
834
cleanFeatures.add(featureDefinition);
835
} catch (InvalidFeatureDefinitionException e) {
836
exceptions.add(e);
837
}
838
}
839
840
// If the broken features has been fixed remove it from the broken list
841
for (FeatureDefinition featureDefinition : cleanFeatures) {
842
invalidFeatureDefinitions.remove(featureDefinition.getId());
843
addFeatureDefinition(featureDefinition);
844
}
845
846
// Verify feature Definitions
847
for (FeatureDefinition featureDefinition : featureDefinitionsCache.values()) {
848
try {
849
if (buildInfoCache == null) {
850
featureDefinition.verify(flagDefinitionsCache, new HashSet<String>());
851
} else {
852
featureDefinition.verify(flagDefinitionsCache, buildInfoCache.getSources());
853
}
854
} catch (InvalidFeatureDefinitionException e) {
855
String featureDefinitionId = (featureDefinition == null) ? e.getObjectId() : featureDefinition.getId();
856
errors.put("feature:" + featureDefinitionId, e); //$NON-NLS-1$
857
brokenFeatures.add(featureDefinition);
858
exceptions.add(e);
859
}
860
}
861
862
// If a feature is broken then add it to the broken list
863
for (FeatureDefinition featureDefinition : brokenFeatures) {
864
removeFeatureDefinition(featureDefinition.getId());
865
invalidFeatureDefinitions.put(featureDefinition.getId(), featureDefinition);
866
}
867
868
// Check build specs that were broken
869
// If they have been fixed then add them back
870
for (BuildSpec buildSpec : invalidBuildSpecs.values()) {
871
try {
872
buildSpec.verify(flagDefinitionsCache, buildInfoCache);
873
cleanSpecs.add(buildSpec);
874
} catch (InvalidBuildSpecException e) {
875
exceptions.add(e);
876
}
877
}
878
879
// If the broken spec has been fixed remove it from the broken list
880
for (BuildSpec buildSpec : cleanSpecs) {
881
invalidBuildSpecs.remove(buildSpec.getId());
882
addBuildSpec(buildSpec);
883
}
884
885
// Verify build specs
886
for (BuildSpec buildSpec : buildSpecCache.values()) {
887
try {
888
buildSpec.verify(flagDefinitionsCache, buildInfoCache);
889
} catch (InvalidBuildSpecException e) {
890
String buildSpecId = (buildSpec == null) ? e.getObjectId() : buildSpec.getIdFromFile();
891
errors.put("buildspec:" + buildSpecId, e); //$NON-NLS-1$
892
brokenSpecs.add(buildSpec);
893
exceptions.add(e);
894
}
895
}
896
897
// If a build spec is broken then add it to the broken list
898
for (BuildSpec buildSpec : brokenSpecs) {
899
removeBuildSpec(buildSpec.getId());
900
invalidBuildSpecs.put(buildSpec.getId(), buildSpec);
901
}
902
903
if (exceptions.size() > 0) {
904
throw new InvalidFactoryException(exceptions, this);
905
}
906
}
907
}
908
909