Path: blob/master/sourcetools/objectmodel/com/ibm/j9tools/om/ObjectFactory.java
6004 views
/*******************************************************************************1* Copyright (c) 2007, 2019 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* 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-exception20*******************************************************************************/21package com.ibm.j9tools.om;2223import java.io.File;24import java.io.IOException;25import java.io.InputStream;26import java.util.Collection;27import java.util.Collections;28import java.util.HashMap;29import java.util.HashSet;30import java.util.Map;31import java.util.Set;32import java.util.TreeMap;33import java.util.TreeSet;3435import com.ibm.j9tools.om.io.BuildInfoParser;36import com.ibm.j9tools.om.io.BuildSpecParser;37import com.ibm.j9tools.om.io.FeatureParser;38import com.ibm.j9tools.om.io.FlagDefinitionParser;3940/**41* The ObjectFactory provides a convenient way of turning files into object model classes.42*43* @author Gabriel Castro44* @author Han Xu45*/46public class ObjectFactory {47/** The configuration directory that will be scanned for flag definitions and feature references. */48private final ConfigDirectory configDirectory;4950private BuildInfo buildInfoCache;51private FlagDefinitions flagDefinitionsCache;52private Map<String, FeatureDefinition> featureDefinitionsCache;53private Map<String, BuildSpec> buildSpecCache;5455private Map<String, BuildSpec> invalidBuildSpecs;56private Map<String, FeatureDefinition> invalidFeatureDefinitions;5758private final Map<String, Throwable> errors = new HashMap<String, Throwable>();5960/**61* Creates a new ObjectFactory which will load from the specified <code>configDirectory</code>.62*63* @param configDirectory The directory from which resources will be loaded.64*/65public ObjectFactory(ConfigDirectory configDirectory) {66this.configDirectory = configDirectory;6768flushCaches();69}7071/**72* Flush all cached values.73*/74public void flushCaches() {75buildInfoCache = null;76flagDefinitionsCache = null;77featureDefinitionsCache = new HashMap<String, FeatureDefinition>();78buildSpecCache = new HashMap<String, BuildSpec>();79invalidBuildSpecs = new HashMap<String, BuildSpec>();80invalidFeatureDefinitions = new HashMap<String, FeatureDefinition>();81}8283/**84* Retrieves this {@link ObjectFactory}'s config directory.85*86* @return the config directory87*/88public ConfigDirectory getConfigDirectory() {89return configDirectory;90}9192/**93* Sets this {@link ObjectFactory}'s flag definitions.94*95* @param defs the new flag definitions96*/97public void setFlagDefinitions(FlagDefinitions defs) {98flagDefinitionsCache = (defs != null) ? defs : new FlagDefinitions();99flagDefinitionsCache.setRuntime(buildInfoCache.getRuntime());100101Collection<IFlagContainer> flagContainers = new HashSet<IFlagContainer>();102103flagContainers.addAll(featureDefinitionsCache.values());104flagContainers.addAll(invalidFeatureDefinitions.values());105flagContainers.addAll(buildSpecCache.values());106flagContainers.addAll(invalidBuildSpecs.values());107108resetFlagDefinitions(flagContainers);109}110111private void resetFlagDefinitions(Collection<IFlagContainer> containers) {112for (IFlagContainer container : containers) {113for (Flag flag : container.getLocalFlags().values()) {114if (flagDefinitionsCache.contains(flag.getId())) {115flag.setDefinition(flagDefinitionsCache.getFlagDefinition(flag.getId()));116} else {117flag.removeDefinition();118}119}120}121}122123/**124* Retrieves all the flag definitions for this <code>ObjectFactory</code>.125*126* @return the flag definitions127*/128public FlagDefinitions getFlagDefinitions() {129return flagDefinitionsCache;130}131132/**133* Sets the cached build info.134*135* @param buildInfo the build info to be cached136*/137public void setBuildInfo(BuildInfo buildInfo) {138buildInfoCache = buildInfo;139}140141/**142* Retrieves the cached build info.143*144* @return The newly loaded build information.145*/146public BuildInfo getBuildInfo() {147return buildInfoCache;148}149150/**151* Adds the {@link BuildSpec} to the valid build spec cache. If a {@link BuildSpec} with the same ID152* already exists in the cache it is overwritten.153*154* @param buildSpec the build spec to be added155*/156public void addBuildSpec(BuildSpec buildSpec) {157if (invalidBuildSpecs.containsKey(buildSpec.getId())) {158// Remove any errors associated with the invalid spec before removing it159errors.remove("buildspec:" + buildSpec.getId()); //$NON-NLS-1$160invalidBuildSpecs.remove(buildSpec.getId());161}162163buildSpec.setRuntime(buildInfoCache.getRuntime());164buildSpecCache.put(buildSpec.getId(), buildSpec);165}166167/**168* Adds the {@link BuildSpec} in the given {@link InvalidBuildSpecException} to the invalid build169* spec cache. If a {@link BuildSpec} with the same ID already exists in the cache it is overwritten.170*171* @param e the exception containing the invalid build spec to be added172*/173public void addInvalidBuildSpec(InvalidBuildSpecException e) {174if (e.getObject() != null) {175errors.put("buildspec:" + e.getObject().getId(), e); //$NON-NLS-1$176invalidBuildSpecs.put(e.getObject().getId(), e.getObject());177}178}179180/**181* Removes the given <code>BuildSpec</code> from the valid build spec cache.182*183* @param buildSpecId the ID of the build spec to be removed184* @return the build spec removed185*/186public BuildSpec removeBuildSpec(String buildSpecId) {187return buildSpecCache.remove(buildSpecId);188}189190/**191* Removes the given {@link BuildSpec} from the invalid build spec cache.192*193* @param buildSpecId the ID of the build spec to be removed194* @return the build spec removed195*/196public BuildSpec removeInvalidBuildSpec(String buildSpecId) {197// Remove any errors associated with the invalid spec before removing it198errors.remove("buildspec:" + buildSpecId); //$NON-NLS-1$199return invalidBuildSpecs.remove(buildSpecId);200}201202/**203* Adds the given {@link FeatureDefinition} to the valid feature cache. If a {@link FeatureDefinition}204* with the same ID already exists in the cache it is overwritten. Adding a feature definition205* will also link it to any {@link BuildSpec} that includes a {@link Feature} of the same ID.206*207* @param featureDefinition the feature definition to be added208*/209public void addFeatureDefinition(FeatureDefinition featureDefinition) {210for (BuildSpec buildSpec : buildSpecCache.values()) {211if (buildSpec.hasFeature(featureDefinition.getId())) {212buildSpec.getFeature(featureDefinition.getId()).setDefinition(featureDefinition);213}214}215216for (BuildSpec buildSpec : invalidBuildSpecs.values()) {217if (buildSpec.hasFeature(featureDefinition.getId())) {218buildSpec.getFeature(featureDefinition.getId()).setDefinition(featureDefinition);219}220}221222if (invalidFeatureDefinitions.containsKey(featureDefinition.getId())) {223// Remove any errors associated with the invalid feature definition before removing it224errors.remove("feature:" + featureDefinition.getId()); //$NON-NLS-1$225invalidFeatureDefinitions.remove(featureDefinition.getId());226}227228featureDefinition.setRuntime(buildInfoCache.getRuntime());229featureDefinitionsCache.put(featureDefinition.getId(), featureDefinition);230}231232/**Adds the {@link FeatureDefinition} in the given {@link InvalidFeatureDefinitionException} to233* the invalid feature cache. If a {@link FeatureDefinition} with the same ID already exists in234* the cache it is overwritten.235*236* @param e the exception containing the invalid feature definition to be added237*/238public void addInvalidFeatureDefinition(InvalidFeatureDefinitionException e) {239if (e.getObject() != null) {240errors.put("feature:" + e.getObject().getId(), e); //$NON-NLS-1$241invalidFeatureDefinitions.put(e.getObject().getId(), e.getObject());242}243}244245/**246* Removes the {@link FeatureDefinition} with the given ID from the valid feature cache. This also removes247* any links to this {@link FeatureDefinition} from all {@link BuildSpec}s including it.248*249* @param featureId the ID of the feature definition to be removed250* @return the removed feature251*/252public FeatureDefinition removeFeatureDefinition(String featureId) {253for (BuildSpec buildSpec : buildSpecCache.values()) {254if (buildSpec.hasFeature(featureId)) {255buildSpec.getFeature(featureId).removeDefinition();256}257}258259for (BuildSpec buildSpec : invalidBuildSpecs.values()) {260if (buildSpec.hasFeature(featureId)) {261buildSpec.getFeature(featureId).removeDefinition();262}263}264265return featureDefinitionsCache.remove(featureId);266}267268/**269* Removes the {@link FeatureDefinition} with the given ID from the invalid feature cache.270*271* @param featureId the ID of the feature definition to be removed272* @return the removed feature273*/274public FeatureDefinition removeInvalidFeatureDefinition(String featureId) {275// Remove any errors associated with the invalid feature definition before removing it276errors.remove("feature:" + featureId); //$NON-NLS-1$277return invalidFeatureDefinitions.remove(featureId);278}279280/**281* Loads the {@link FlagDefinitions} found in the given {@link File}.282*283* @param file the file containing flag definitions284* @return the parsed flag definitions285*286* @throws InvalidFlagDefinitionsException thrown if errors are found while parsing the flag definitions file287*/288public FlagDefinitions loadFlagDefinitions(File file) throws InvalidFlagDefinitionsException {289FlagDefinitionParser parser = new FlagDefinitionParser();290FlagDefinitions defs = null;291292try {293defs = parser.parse(file);294} catch (IOException e) {295throw new InvalidFlagDefinitionsException(e, "flags"); //$NON-NLS-1$296}297298try {299defs.verify();300} catch (InvalidFlagDefinitionsException e) {301throw new InvalidFlagDefinitionsException(e.getErrors(), defs);302}303304defs.setRuntime(buildInfoCache.getRuntime());305306return defs;307}308309/**310* Loads the {@link FlagDefinitions} found in the given {@link File}.311*312* @param inputStream the input stream containing flag definitions313* @return the parsed flag definitions314*315* @throws InvalidFlagDefinitionsException thrown if errors are found while parsing the flag definitions input stream316*/317public FlagDefinitions loadFlagDefinitions(InputStream inputStream) throws InvalidFlagDefinitionsException {318FlagDefinitionParser parser = new FlagDefinitionParser();319FlagDefinitions defs = null;320321try {322defs = parser.parse(inputStream);323} catch (IOException e) {324throw new InvalidFlagDefinitionsException(e, "flags"); //$NON-NLS-1$325}326327try {328defs.verify();329} catch (InvalidFlagDefinitionsException e) {330throw new InvalidFlagDefinitionsException(e.getErrors(), defs);331}332333defs.setRuntime(buildInfoCache.getRuntime());334335return defs;336}337338/**339* Loads the {@link BuildInfo} found in the given {@link File}.340*341* @param file the file containing the build info342* @return the parsed build info343*344* @throws InvalidBuildInfoException thrown if errors are found while parsing the build info file345*/346public BuildInfo loadBuildInfo(File file) throws InvalidBuildInfoException {347BuildInfo buildInfo;348349try {350BuildInfoParser parser = new BuildInfoParser();351buildInfo = parser.parse(file);352} catch (IOException e) {353throw new InvalidBuildInfoException(e, "buildInfo"); //$NON-NLS-1$354}355356return buildInfo;357}358359/**360* Loads the {@link BuildInfo} found in the given {@link InputStream}.361*362* @param inputStream the input stream containing the build info363* @return the parsed build info364*365* @throws InvalidBuildInfoException thrown if errors are found while parsing the build info input stream366*/367public BuildInfo loadBuildInfo(InputStream inputStream) throws InvalidBuildInfoException {368BuildInfo buildInfo;369370try {371BuildInfoParser parser = new BuildInfoParser();372buildInfo = parser.parse(inputStream);373} catch (IOException e) {374throw new InvalidBuildInfoException(e, "buildInfo"); //$NON-NLS-1$375}376377return buildInfo;378}379380/**381* Loads the {@link BuildSpec} found in the given {@link File}.382*383* @param file the spec file.384* @return the parsed build spec.385*386* @throws InvalidBuildSpecException thrown if errors are found while parsing the build spec file387*/388public BuildSpec loadBuildSpec(File file) throws InvalidBuildSpecException {389BuildSpecParser parser = new BuildSpecParser();390BuildSpec buildSpec = null;391392try {393buildSpec = parser.parse(file, flagDefinitionsCache, featureDefinitionsCache);394} catch (IOException e) {395throw new InvalidBuildSpecException(e, file.getName().substring(0, file.getName().length() - ConfigDirectory.BUILD_SPEC_FILE_EXTENSION.length()));396}397398try {399buildSpec.verify(flagDefinitionsCache, buildInfoCache);400} catch (InvalidBuildSpecException e) {401buildSpec = e.getObject();402String buildSpecId = (buildSpec == null) ? e.getObjectId() : buildSpec.getIdFromFile();403errors.put("buildspec:" + buildSpecId, e); //$NON-NLS-1$404405if (buildSpec != null) {406invalidBuildSpecs.put(buildSpec.getIdFromFile(), buildSpec);407}408409throw e;410}411412buildSpec.setRuntime(buildInfoCache.getRuntime());413414return buildSpec;415}416417/**418* Loads the {@link BuildSpec} found in the given {@link InputStream}.419*420* @param inputStream the build spec input stream421* @return the newly loaded build spec.422*423* @throws InvalidBuildSpecException thrown if errors are found while parsing the build spec input stream424*/425public BuildSpec loadBuildSpec(InputStream inputStream, String objectId) throws InvalidBuildSpecException {426BuildSpecParser parser = new BuildSpecParser();427BuildSpec buildSpec = null;428429try {430buildSpec = parser.parse(inputStream, objectId, flagDefinitionsCache, featureDefinitionsCache);431} catch (IOException e) {432throw new InvalidBuildSpecException(e, objectId);433}434435try {436buildSpec.verify(flagDefinitionsCache, buildInfoCache);437} catch (InvalidBuildSpecException e) {438buildSpec = e.getObject();439String buildSpecId = (buildSpec == null) ? e.getObjectId() : buildSpec.getIdFromFile();440errors.put("buildspec:" + buildSpecId, e); //$NON-NLS-1$441442if (buildSpec != null) {443invalidBuildSpecs.put(buildSpec.getIdFromFile(), buildSpec);444}445446throw e;447}448449buildSpec.setRuntime(buildInfoCache.getRuntime());450451return buildSpec;452}453454/**455* Loads the {@link FeatureDefinition} found in the given {@link File}.456*457* @param file the feature definition file458* @return the newly loaded feature definition459*460* @throws InvalidFeatureDefinitionException thrown if errors are found while parsing the feature definition file461*/462public FeatureDefinition loadFeatureDefinition(File file) throws InvalidFeatureDefinitionException {463FeatureParser parser = new FeatureParser();464FeatureDefinition featureDefinition = null;465466try {467featureDefinition = parser.parse(file, flagDefinitionsCache);468} catch (IOException e) {469throw new InvalidFeatureDefinitionException(e, file.getName().substring(0, file.getName().length() - ConfigDirectory.FEATURE_FILE_EXTENSION.length()));470}471472try {473if (buildInfoCache == null) {474featureDefinition.verify(flagDefinitionsCache, new HashSet<String>());475} else {476featureDefinition.verify(flagDefinitionsCache, buildInfoCache.getSources());477}478} catch (InvalidFeatureDefinitionException e) {479featureDefinition = e.getObject();480String featureDefinitionId = (featureDefinition == null) ? e.getObjectId() : featureDefinition.getId();481errors.put("feature:" + featureDefinitionId, e); //$NON-NLS-1$482483if (featureDefinition != null) {484invalidFeatureDefinitions.put(featureDefinition.getId(), featureDefinition);485}486487throw e;488}489490featureDefinition.setRuntime(buildInfoCache.getRuntime());491492return featureDefinition;493}494495/**496* Loads the {@link FeatureDefinition} found in the given {@link InputStream}.497*498* @param inputStream the feature definition input stream499* @return the newly loaded feature definition500*501* @throws InvalidFeatureDefinitionException thrown if errors are found while parsing the feature definition input stream502*/503public FeatureDefinition loadFeatureDefinition(InputStream inputStream, String objectId) throws InvalidFeatureDefinitionException {504FeatureParser parser = new FeatureParser();505FeatureDefinition featureDefinition = null;506507try {508featureDefinition = parser.parse(inputStream, objectId, flagDefinitionsCache);509} catch (IOException e) {510throw new InvalidFeatureDefinitionException(e, objectId);511}512513try {514if (buildInfoCache == null) {515featureDefinition.verify(flagDefinitionsCache, new HashSet<String>());516} else {517featureDefinition.verify(flagDefinitionsCache, buildInfoCache.getSources());518}519} catch (InvalidFeatureDefinitionException e) {520featureDefinition = e.getObject();521String featureDefinitionId = (featureDefinition == null) ? e.getObjectId() : featureDefinition.getId();522errors.put("feature:" + featureDefinitionId, e); //$NON-NLS-1$523524if (featureDefinition != null) {525invalidFeatureDefinitions.put(featureDefinition.getId(), featureDefinition);526}527528throw e;529}530531featureDefinition.setRuntime(buildInfoCache.getRuntime());532533return featureDefinition;534}535536/**537* Retrieves the {@link FeatureDefinition} with the given <code>featureId</code> from the cache.538*539* @param featureId the ID of the desired Feature540* @return the Feature requested541*542* @throws InvalidFeatureDefinitionException if the feature definition contains errors543*/544public FeatureDefinition getFeature(String featureId) throws InvalidFeatureDefinitionException {545if (invalidFeatureDefinitions.containsKey(featureId)) {546throw (InvalidFeatureDefinitionException) errors.get("feature:" + featureId); //$NON-NLS-1$547}548549return featureDefinitionsCache.get(featureId);550}551552public BuildSpec getDefaultActiveSpec() {553int highestPriority = -1;554BuildSpec defaultActiveSpec = null;555556for (BuildSpec spec : buildSpecCache.values()) {557if (spec.getPriority() > highestPriority) {558highestPriority = spec.getPriority();559defaultActiveSpec = spec;560}561}562563return defaultActiveSpec;564}565566/**567* Retrieves the {@link BuildSpec} with the given <code>buildSpecId</code> from the cache.568*569* @param buildSpecId the ID of the desired BuildSpec570* @return the BuildSpec requested571*572* @throws InvalidBuildSpecException573*/574public BuildSpec getBuildSpec(String buildSpecId) throws InvalidBuildSpecException {575if (invalidBuildSpecs.containsKey(buildSpecId)) {576throw (InvalidBuildSpecException) errors.get("buildspec:" + buildSpecId); //$NON-NLS-1$577}578579return buildSpecCache.get(buildSpecId);580}581582/**583* Retrieves a list of all the valid {@link BuildSpec}s in the factory's config directory.584*585* @return a list of all the valid build specs586*/587public Collection<BuildSpec> getBuildSpecs() {588return buildSpecCache.values();589}590591public Collection<BuildSpec> getAllBuildSpecs() {592Map<String, BuildSpec> temp = new TreeMap<String, BuildSpec>();593temp.putAll(buildSpecCache);594595for (String specID : invalidBuildSpecs.keySet()) {596if (invalidBuildSpecs.get(specID) != null) {597temp.put(specID, invalidBuildSpecs.get(specID));598}599}600601return temp.values();602}603604/**605* Retrieves the list of all valid {@link BuildSpec} IDs in this factory's config directory.606*607* @return a list of all valid build spec IDs608*/609public Set<String> getBuildSpecIds() {610return buildSpecCache.keySet();611}612613/**614* Retrieves the map of all valid {@link BuildSpec}s in this factory's config directory.615*616* @return a map of all valid build specs617*/618public Map<String, BuildSpec> getBuildSpecsMap() {619return Collections.unmodifiableMap(buildSpecCache);620}621622/**623* Returns a <code>Set</code> containing all the OS types for the specs in this <code>ObjectFactory</code>.624*625* @return the OS types for all the build specs626*/627public Set<String> getBuildSpecOSes() {628Set<String> buildSpecOSes = new TreeSet<String>();629630for (BuildSpec spec : buildSpecCache.values()) {631buildSpecOSes.add(spec.getOs());632}633634return buildSpecOSes;635}636637/**638* Retrieves the valid build specs for the given OS.639*640* @param os the OS for which to return build specs641* @return the build specs of the given OS642*/643public Set<BuildSpec> getBuildSpecsByOS(String os) {644Set<BuildSpec> buildSpecs = new TreeSet<BuildSpec>();645646for (BuildSpec buildSpec : buildSpecCache.values()) {647if (os.equals(buildSpec.getOs())) {648buildSpecs.add(buildSpec);649}650}651652return buildSpecs;653}654655/**656* Retrieves the list of J9 Specifications that have the given feature. Returns an empty set657* if the feature ID is null or an empty string.658*659* @param featureID the ID of the feature to be searched for660* @return the set of specs with the given feature, or an empty set if none exist or the661* feature ID is not valid662*/663public Set<BuildSpec> getBuildSpecsByFeature(String featureID) {664Set<BuildSpec> buildSpecs = new TreeSet<BuildSpec>();665666if (featureID != null && featureID.length() > 0) {667for (BuildSpec spec : buildSpecCache.values()) {668if (spec.getFeatures().keySet().contains(featureID)) {669buildSpecs.add(spec);670}671}672}673674return buildSpecs;675}676677/**678* Retrieves the list of J9 Specification IDs that have the given feature. Returns an empty set679* if the feature ID is null or an empty string.680*681* @param featureID the ID of the feature to be searched for682* @return the set of spec IDs with the given feature, or an empty set if none exist or the683* feature ID is not valid684*/685public Set<String> getBuildSpecIDsByFeature(String featureID) {686Set<String> buildSpecs = new TreeSet<String>();687688if (featureID != null && featureID.length() > 0) {689for (BuildSpec spec : buildSpecCache.values()) {690if (spec.getFeatures().keySet().contains(featureID)) {691buildSpecs.add(spec.getId());692}693}694}695696return buildSpecs;697}698699/**700* Retrieves the valid {@link FeatureDefinition}s in the factory's config directory.701*702* @return the valid feature definitions703*/704public Collection<FeatureDefinition> getFeatureDefinitions() {705return featureDefinitionsCache.values();706}707708/**709* Retrieves the set of valid {@link FeatureDefinition} IDs the factory's config directory.710*711* @return the valid feature definition IDs712*/713public Set<String> getFeatureDefinitionIds() {714return featureDefinitionsCache.keySet();715}716717/**718* Retrieves the map of valid {@link FeatureDefinition}s the factory's config directory.719*720* @return the valid feature definitions721*/722public Map<String, FeatureDefinition> getFeatureDefinitionsMap() {723return Collections.unmodifiableMap(featureDefinitionsCache);724}725726/**727* Loads a runtime's build-info, flag definitions as well as all the valid build specs and features728* contained in this <code>ObjectFactory</code>'s config directory.729*730* Errors found when loading the build-info and flag definitions are considered fatal and will result731* on an {@link InvalidFactoryException} being thrown (even if errors are delayed). Errors found732* when loading features or build specs will result in that element not being loaded into the factory.733*734* @param delayErrors delay throwing exceptions unless error is critical (build-info or flags invalid)735*736* @throws InvalidFactoryException thrown if errors are found when initializing factory elements737*/738public void initialize(boolean delayErrors) throws InvalidFactoryException {739boolean notDelayable = false;740741// Load basic information742try {743buildInfoCache = loadBuildInfo(configDirectory.getBuildInfoFile());744} catch (InvalidBuildInfoException e) {745buildInfoCache = e.getObject();746errors.put("buildInfo", e); //$NON-NLS-1$747notDelayable = true;748}749750// Can't parse much more if we don't even have a partial build-info751if (buildInfoCache != null) {752// Load flag definitions753try {754flagDefinitionsCache = loadFlagDefinitions(configDirectory.getFlagDefinitionsFile());755} catch (InvalidFlagDefinitionsException e) {756flagDefinitionsCache = (e.getObject() == null) ? new FlagDefinitions() : e.getObject();757errors.put("flags", e); //$NON-NLS-1$758notDelayable = true;759}760761// Load features762for (File file : configDirectory.getFeatureFiles()) {763FeatureDefinition featureDefinition;764765try {766featureDefinition = loadFeatureDefinition(file);767featureDefinitionsCache.put(featureDefinition.getId(), featureDefinition);768} catch (InvalidFeatureDefinitionException e) {769errors.put("feature:" + e.getObjectId(), e); //$NON-NLS-1$770}771}772773// Load build specs774for (File file : configDirectory.getBuildSpecFiles()) {775BuildSpec buildSpec;776777try {778buildSpec = loadBuildSpec(file);779buildSpecCache.put(buildSpec.getId(), buildSpec);780} catch (InvalidBuildSpecException e) {781errors.put("buildspec:" + e.getObjectId(), e); //$NON-NLS-1$782}783}784}785786if (errors.size() > 0 && (!delayErrors || notDelayable)) {787throw new InvalidFactoryException(errors.values(), this);788}789}790791/**792* Initializes the factory without delaying errors found.793*794* @see #initialize(boolean)795*796* @throws InvalidFactoryException thrown if errors are found when initializing factory elements797*/798public void initialize() throws InvalidFactoryException {799initialize(false);800}801802/**803* Verifies the flag definitions, features, and build specs for validity. This is to be used804* when modifying elements on a object factory that has already been initialized.805*806* @throws InvalidFactoryException thrown if errors are found when verifying factory elements807*/808public void verify() throws InvalidFactoryException {809Set<Throwable> exceptions = new HashSet<Throwable>();810811Set<BuildSpec> brokenSpecs = new HashSet<BuildSpec>();812Set<BuildSpec> cleanSpecs = new HashSet<BuildSpec>();813Set<FeatureDefinition> brokenFeatures = new HashSet<FeatureDefinition>();814Set<FeatureDefinition> cleanFeatures = new HashSet<FeatureDefinition>();815816// Verify flag definitions817try {818flagDefinitionsCache.verify();819} catch (InvalidFlagDefinitionsException e) {820exceptions.add(e);821}822823// Check features that were broken824// If they have been fixed then add them back825for (FeatureDefinition featureDefinition : invalidFeatureDefinitions.values()) {826try {827if (buildInfoCache == null) {828featureDefinition.verify(flagDefinitionsCache, new HashSet<String>());829} else {830featureDefinition.verify(flagDefinitionsCache, buildInfoCache.getSources());831}832833cleanFeatures.add(featureDefinition);834} catch (InvalidFeatureDefinitionException e) {835exceptions.add(e);836}837}838839// If the broken features has been fixed remove it from the broken list840for (FeatureDefinition featureDefinition : cleanFeatures) {841invalidFeatureDefinitions.remove(featureDefinition.getId());842addFeatureDefinition(featureDefinition);843}844845// Verify feature Definitions846for (FeatureDefinition featureDefinition : featureDefinitionsCache.values()) {847try {848if (buildInfoCache == null) {849featureDefinition.verify(flagDefinitionsCache, new HashSet<String>());850} else {851featureDefinition.verify(flagDefinitionsCache, buildInfoCache.getSources());852}853} catch (InvalidFeatureDefinitionException e) {854String featureDefinitionId = (featureDefinition == null) ? e.getObjectId() : featureDefinition.getId();855errors.put("feature:" + featureDefinitionId, e); //$NON-NLS-1$856brokenFeatures.add(featureDefinition);857exceptions.add(e);858}859}860861// If a feature is broken then add it to the broken list862for (FeatureDefinition featureDefinition : brokenFeatures) {863removeFeatureDefinition(featureDefinition.getId());864invalidFeatureDefinitions.put(featureDefinition.getId(), featureDefinition);865}866867// Check build specs that were broken868// If they have been fixed then add them back869for (BuildSpec buildSpec : invalidBuildSpecs.values()) {870try {871buildSpec.verify(flagDefinitionsCache, buildInfoCache);872cleanSpecs.add(buildSpec);873} catch (InvalidBuildSpecException e) {874exceptions.add(e);875}876}877878// If the broken spec has been fixed remove it from the broken list879for (BuildSpec buildSpec : cleanSpecs) {880invalidBuildSpecs.remove(buildSpec.getId());881addBuildSpec(buildSpec);882}883884// Verify build specs885for (BuildSpec buildSpec : buildSpecCache.values()) {886try {887buildSpec.verify(flagDefinitionsCache, buildInfoCache);888} catch (InvalidBuildSpecException e) {889String buildSpecId = (buildSpec == null) ? e.getObjectId() : buildSpec.getIdFromFile();890errors.put("buildspec:" + buildSpecId, e); //$NON-NLS-1$891brokenSpecs.add(buildSpec);892exceptions.add(e);893}894}895896// If a build spec is broken then add it to the broken list897for (BuildSpec buildSpec : brokenSpecs) {898removeBuildSpec(buildSpec.getId());899invalidBuildSpecs.put(buildSpec.getId(), buildSpec);900}901902if (exceptions.size() > 0) {903throw new InvalidFactoryException(exceptions, this);904}905}906}907908909