Files
Orchard/src/Orchard.Web/Modules/Futures.Modules.Packaging/Services/PackageExpander.cs

172 lines
7.0 KiB
C#
Raw Normal View History

using System;
using System.IO;
using System.IO.Packaging;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
using Orchard.Environment.Extensions;
using Orchard.FileSystems.VirtualPath;
using Orchard.FileSystems.WebSite;
namespace Futures.Modules.Packaging.Services {
public class PackageExpander : IPackageExpander {
private const string ContentTypePrefix = "Orchard ";
private readonly IExtensionManager _extensionManager;
private readonly IWebSiteFolder _webSiteFolder;
private readonly IVirtualPathProvider _virtualPathProvider;
public PackageExpander(
IExtensionManager extensionManager,
IWebSiteFolder webSiteFolder,
IVirtualPathProvider virtualPathProvider) {
_extensionManager = extensionManager;
_webSiteFolder = webSiteFolder;
_virtualPathProvider = virtualPathProvider;
}
class ExpandContext {
public Stream Stream { get; set; }
public Package Package { get; set; }
public string ExtensionName { get; set; }
public string ExtensionType { get; set; }
public string TargetPath { get; set; }
public string SourcePath { get; set; }
public XDocument Project { get; set; }
}
public void ExpandPackage(Stream packageStream) {
var context = new ExpandContext();
BeginPackage(context, packageStream);
try {
GetCoreProperties(context);
EstablishPaths(context, _virtualPathProvider);
var projectFile = context.ExtensionName + ".csproj";
if (LoadProject(context, projectFile)) {
ExtractFile(context, projectFile);
ExtractProjectFiles(context, "Compile", "Content", "None", "EmbeddedResource");
ExtractReferenceFiles(context);
}
}
finally {
EndPackage(context);
}
}
private void ExtractFile(ExpandContext context, string relativePath) {
var partUri = PackUriHelper.CreatePartUri(new Uri(context.SourcePath + relativePath, UriKind.Relative));
var packagePart = context.Package.GetPart(partUri);
using (var packageStream = packagePart.GetStream(FileMode.Open, FileAccess.Read)) {
var filePath = Path.Combine(context.TargetPath, relativePath);
var folderPath = Path.GetDirectoryName(filePath);
if (!Directory.Exists(folderPath))
Directory.CreateDirectory(folderPath);
using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Read)) {
packageStream.CopyTo(fileStream);
}
}
}
private void ExtractProjectFiles(ExpandContext context, params string[] itemGroupTypes) {
var itemGroups = context.Project
.Elements(Ns("Project"))
.Elements(Ns("ItemGroup"));
foreach (var itemGroupType in itemGroupTypes) {
var includePaths = itemGroups
.Elements(Ns(itemGroupType))
.Attributes("Include")
.Select(x => x.Value);
foreach (var includePath in includePaths) {
ExtractFile(context, includePath);
}
}
}
private void ExtractReferenceFiles(ExpandContext context) {
var entries = context.Project
.Elements(Ns("Project"))
.Elements(Ns("ItemGroup"))
.Elements(Ns("Reference"))
.Select(reference => new {
Include = reference.Attribute("Include"),
HintPath = reference.Element(Ns("HintPath"))
})
.Where(entry => entry.Include != null);
foreach (var entry in entries) {
var assemblyName = new AssemblyName(entry.Include.Value);
var hintPath = entry.HintPath != null ? entry.HintPath.Value : null;
var virtualPath = "bin/" + assemblyName.Name + ".dll";
if (PartExists(context, virtualPath)) {
ExtractFile(context, virtualPath);
}
else if (hintPath != null) {
}
}
}
private bool PartExists(ExpandContext context, string relativePath) {
var projectUri = PackUriHelper.CreatePartUri(new Uri(context.SourcePath + relativePath, UriKind.Relative));
return context.Package.PartExists(projectUri);
}
private XName Ns(string localName) {
return XName.Get(localName, "http://schemas.microsoft.com/developer/msbuild/2003");
}
private static bool LoadProject(ExpandContext context, string relativePath) {
var projectUri = PackUriHelper.CreatePartUri(new Uri(context.SourcePath + relativePath, UriKind.Relative));
if (!context.Package.PartExists(projectUri))
return false;
var part = context.Package.GetPart(projectUri);
using (var stream = part.GetStream(FileMode.Open, FileAccess.Read)) {
context.Project = XDocument.Load(stream);
}
return true;
}
private void BeginPackage(ExpandContext context, Stream packageStream) {
if (packageStream.CanSeek) {
context.Stream = packageStream;
}
else {
context.Stream = new MemoryStream();
packageStream.CopyTo(context.Stream);
}
context.Package = Package.Open(context.Stream, FileMode.Open, FileAccess.Read);
}
private void EndPackage(ExpandContext context) {
context.Package.Close();
}
private void GetCoreProperties(ExpandContext context) {
context.ExtensionName = context.Package.PackageProperties.Identifier;
var contentType = context.Package.PackageProperties.ContentType;
if (contentType.StartsWith(ContentTypePrefix))
context.ExtensionType = contentType.Substring(ContentTypePrefix.Length);
}
private void EstablishPaths(ExpandContext context, IVirtualPathProvider virtualPathProvider) {
context.SourcePath = "\\" + context.ExtensionName + "\\";
if (context.ExtensionType == "Theme") {
context.TargetPath = virtualPathProvider.MapPath("~/Themes-temp/" + context.ExtensionName);
}
else if (context.ExtensionType == "Module") {
context.TargetPath = virtualPathProvider.MapPath("~/Modules-temp/" + context.ExtensionName);
}
else {
throw new ApplicationException("Unknown extension type");
}
}
}
}