in src/Tasks/BootstrapperUtil/BootstrapperBuilder.cs [900:1080]
private void ExploreDirectory(string strSubDirectory, XmlElement rootElement)
{
try
{
string packagePath = PackagePath;
string strSubDirectoryFullPath = System.IO.Path.Combine(packagePath, strSubDirectory);
// figure out our product file paths based on the directory full path
string strBaseManifestFilename = System.IO.Path.Combine(strSubDirectoryFullPath, ROOT_MANIFEST_FILE);
string strBaseManifestSchemaFileName = System.IO.Path.Combine(SchemaPath, MANIFEST_FILE_SCHEMA);
ProductValidationResults productValidationResults = new ProductValidationResults(strBaseManifestFilename);
// open the XmlDocument for this product.xml
XmlDocument productDoc = LoadAndValidateXmlDocument(strBaseManifestFilename, false, strBaseManifestSchemaFileName, BOOTSTRAPPER_NAMESPACE, productValidationResults);
if (productDoc != null)
{
bool packageAdded = false;
XmlNode baseNode = productDoc.SelectSingleNode(BOOTSTRAPPER_PREFIX + ":Product", _xmlNamespaceManager);
if (baseNode != null)
{
// Get the ProductCode attribute for this product
XmlAttribute productCodeAttribute = (XmlAttribute)(baseNode.Attributes.GetNamedItem("ProductCode"));
if (productCodeAttribute != null)
{
// now add it to our full document if it's not already present
XmlNode productNode = rootElement.SelectSingleNode(BOOTSTRAPPER_PREFIX + ":Product[@ProductCode='" + productCodeAttribute.Value + "']", _xmlNamespaceManager);
if (productNode == null)
{
productNode = CreateProductNode(baseNode);
}
else
{
productValidationResults = (ProductValidationResults)_validationResults[productCodeAttribute];
}
// Fix-up the <PackageFiles> of the base node to include the SourcePath and TargetPath
XmlNode packageFilesNode = baseNode.SelectSingleNode(BOOTSTRAPPER_PREFIX + ":PackageFiles", _xmlNamespaceManager);
XmlNode checksNode = baseNode.SelectSingleNode(BOOTSTRAPPER_PREFIX + ":InstallChecks", _xmlNamespaceManager);
XmlNode commandsNode = baseNode.SelectSingleNode(BOOTSTRAPPER_PREFIX + ":Commands", _xmlNamespaceManager);
// if there was a packageFiles node, then add it in to our full document with the rest
if (packageFilesNode != null)
{
UpdatePackageFileNodes(packageFilesNode, System.IO.Path.Combine(packagePath, strSubDirectory), strSubDirectory);
ReplacePackageFileAttributes(checksNode, "PackageFile", packageFilesNode, "PackageFile", "OldName", "Name");
ReplacePackageFileAttributes(commandsNode, "PackageFile", packageFilesNode, "PackageFile", "OldName", "Name");
ReplacePackageFileAttributes(baseNode, EULA_ATTRIBUTE, packageFilesNode, "PackageFile", "OldName", "SourcePath");
}
foreach (string strLanguageDirectory in Directory.GetDirectories(strSubDirectoryFullPath))
{
// The base node would get destroyed as we build-up this new node.
// Thus, we want to use a copy of the baseNode
XmlElement baseElement = (XmlElement)(_document.ImportNode(baseNode, true));
string strLangManifestFilename = System.IO.Path.Combine(strLanguageDirectory, CHILD_MANIFEST_FILE);
string strLangManifestSchemaFileName = System.IO.Path.Combine(SchemaPath, MANIFEST_FILE_SCHEMA);
if (File.Exists(strLangManifestFilename))
{
// Load Package.xml
XmlValidationResults packageValidationResults = new XmlValidationResults(strLangManifestFilename);
XmlDocument langDoc = LoadAndValidateXmlDocument(strLangManifestFilename, false, strLangManifestSchemaFileName, BOOTSTRAPPER_NAMESPACE, packageValidationResults);
Debug.Assert(langDoc != null, "we couldn't load package.xml in '" + strLangManifestFilename + "'...?");
if (langDoc == null)
continue;
XmlNode langNode = langDoc.SelectSingleNode(BOOTSTRAPPER_PREFIX + ":Package", _xmlNamespaceManager);
Debug.Assert(langNode != null, string.Format(CultureInfo.CurrentCulture, "Unable to find a package node in {0}", strLangManifestFilename));
if (langNode != null)
{
XmlElement langElement = (XmlElement)(_document.ImportNode(langNode, true));
XmlElement mergeElement = _document.CreateElement("Package", BOOTSTRAPPER_NAMESPACE);
// Update the "PackageFiles" section to reflect this language subdirectory
XmlNode packageFilesNodePackage = langElement.SelectSingleNode(BOOTSTRAPPER_PREFIX + ":PackageFiles", _xmlNamespaceManager);
checksNode = langElement.SelectSingleNode(BOOTSTRAPPER_PREFIX + ":InstallChecks", _xmlNamespaceManager);
commandsNode = langElement.SelectSingleNode(BOOTSTRAPPER_PREFIX + ":Commands", _xmlNamespaceManager);
if (packageFilesNodePackage != null)
{
int nStartIndex = packagePath.Length;
if ((strLanguageDirectory.ToCharArray())[nStartIndex] == System.IO.Path.DirectorySeparatorChar)
nStartIndex++;
UpdatePackageFileNodes(packageFilesNodePackage, strLanguageDirectory, strSubDirectory);
ReplacePackageFileAttributes(checksNode, "PackageFile", packageFilesNodePackage, "PackageFile", "OldName", "Name");
ReplacePackageFileAttributes(commandsNode, "PackageFile", packageFilesNodePackage, "PackageFile", "OldName", "Name");
ReplacePackageFileAttributes(langElement, EULA_ATTRIBUTE, packageFilesNodePackage, "PackageFile", "OldName", "SourcePath");
}
if (packageFilesNode != null)
{
ReplacePackageFileAttributes(checksNode, "PackageFile", packageFilesNode, "PackageFile", "OldName", "Name");
ReplacePackageFileAttributes(commandsNode, "PackageFile", packageFilesNode, "PackageFile", "OldName", "Name");
ReplacePackageFileAttributes(langElement, EULA_ATTRIBUTE, packageFilesNode, "PackageFile", "OldName", "SourcePath");
}
// in general, we prefer the attributes of the language document over the
// attributes of the base document. Copy attributes from the lang to the merged,
// and then merge all unique elements into merge
foreach (XmlAttribute attribute in langElement.Attributes)
{
mergeElement.Attributes.Append((XmlAttribute)(mergeElement.OwnerDocument.ImportNode(attribute, false)));
}
foreach (XmlAttribute attribute in baseElement.Attributes)
{
XmlAttribute convertedAttribute = (XmlAttribute)(mergeElement.OwnerDocument.ImportNode(attribute, false));
MergeAttribute(mergeElement, convertedAttribute);
}
// And append all of the nodes
// There is a well-known set of nodes which may have inherit children
// When merging these nodes, there may be subnodes taken from both the lang element and the base element.
// There will never be multiple nodes with the same name in the same manifest
// The function which performs this action is CombineElements(...)
CombineElements(langElement, baseElement, "Commands", "PackageFile", mergeElement);
CombineElements(langElement, baseElement, "InstallChecks", "Property", mergeElement);
CombineElements(langElement, baseElement, "PackageFiles", "Name", mergeElement);
CombineElements(langElement, baseElement, "Schedules", "Name", mergeElement);
CombineElements(langElement, baseElement, "Strings", "Name", mergeElement);
ReplaceStrings(mergeElement);
CorrectPackageFiles(mergeElement);
AppendNode(baseElement, "RelatedProducts", mergeElement);
// Create a unique identifier for this package
XmlAttribute cultureAttribute = (XmlAttribute)mergeElement.Attributes.GetNamedItem("Culture");
if (cultureAttribute != null && !String.IsNullOrEmpty(cultureAttribute.Value))
{
string packageCode = productCodeAttribute.Value + "." + cultureAttribute.Value;
AddAttribute(mergeElement, "PackageCode", packageCode);
if (productValidationResults != null && packageValidationResults != null)
{
productValidationResults.AddPackageResults(cultureAttribute.Value, packageValidationResults);
}
// Only add this package if there is a culture apecified.
productNode.AppendChild(mergeElement);
packageAdded = true;
}
}
}
}
if (packageAdded)
{
rootElement.AppendChild(productNode);
if (!_validationResults.Contains(productCodeAttribute.Value))
{
_validationResults.Add(productCodeAttribute.Value, productValidationResults);
}
else
{
Debug.WriteLine(String.Format(CultureInfo.CurrentCulture, "Validation results already added for Product Code '{0}'", productCodeAttribute));
}
}
}
}
}
}
catch (XmlException ex)
{
Debug.Fail(ex.Message);
}
catch (System.IO.IOException ex)
{
Debug.Fail(ex.Message);
}
catch (ArgumentException ex)
{
Debug.Fail(ex.Message);
}
}