blob: 879d9c5e5688cb9f621e588398cfbab607aaf9c1 [file] [log] [blame]
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using NPanday.Utils;
using System.Reflection;
using NPanday.Artifact;
using NPanday.Model.Setting;
using System.Windows.Forms;
using System.Net;
/// Author: Leopoldo Lee Agdeppa III
namespace NPanday.ProjectImporter.Digest.Model
{
public class Reference : IncludeBase
{
#region Constructors
public Reference(string projectBasePath, GacUtility gac)
: base(projectBasePath)
{
this.gac = gac;
}
#endregion
#region Properties
private GacUtility gac;
public GacUtility GacUtility
{
get
{
if (gac == null)
{
gac = new GacUtility();
}
return gac;
}
}
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
private string hintPath;
public string HintPath
{
get { return hintPath; }
set
{
if (string.IsNullOrEmpty(value))
{
return;
}
hintPath = value;
SetReferenceFromFile(value);
}
}
public string HintFullPath
{
get
{
if (string.IsNullOrEmpty(hintPath))
{
return null;
}
else if (Path.IsPathRooted(hintPath))
{
return Path.GetFullPath(hintPath);
}
else
{
return Path.GetFullPath(Path.Combine(projectBasePath, hintPath));
}
}
}
public string AssemblyInfo
{
set
{
if (value.Split(',').Length > 1)
{
SetAssemblyInfoValues(value);
}
else
{
SetAssemblyValuesFromGac(value);
}
}
}
private string version;
public string Version
{
get { return version; }
set { version = value; }
}
private string publicKeyToken;
public string PublicKeyToken
{
get { return publicKeyToken; }
set { publicKeyToken = value; }
}
private string culture;
public string Culture
{
get { return culture; }
set { culture = value; }
}
private string processorArchitecture;
public string ProcessorArchitecture
{
get { return processorArchitecture; }
set { processorArchitecture = value; }
}
#endregion
#region HelperMethods
private void SetReferenceFromFile(string dll)
{
if (string.IsNullOrEmpty(dll))
{
return;
}
SetReferenceFromFile(new FileInfo(dll));
}
private void SetReferenceFromFile(FileInfo dll)
{
Assembly asm = null ;
string path = string.Empty;
//if (dll.Exists)
if (dll.Exists)
{
//asm = Assembly.ReflectionOnlyLoadFrom(dll.FullName);
path = dll.FullName;
}
else
{
ArtifactContext artifactContext = new ArtifactContext();
Artifact.Artifact a = artifactContext.GetArtifactRepository().GetArtifact(dll);
if (a != null)
{
if (!a.FileInfo.Exists)
{
if (!a.FileInfo.Directory.Exists)
a.FileInfo.Directory.Create();
string localRepoPath = artifactContext.GetArtifactRepository().GetLocalRepositoryPath(a, dll.Extension);
if (File.Exists(localRepoPath))
{
File.Copy(localRepoPath, a.FileInfo.FullName);
//asm = Assembly.ReflectionOnlyLoadFrom();
path = a.FileInfo.FullName;
}
else
{
if (downloadArtifactFromRemoteRepository(a, dll.Extension,null))
{
//asm = Assembly.ReflectionOnlyLoadFrom(a.FileInfo.FullName);
path = a.FileInfo.FullName;
}
else
{
path = getBinReference(dll.Name);
if (!string.IsNullOrEmpty(path))
{
File.Copy(path, a.FileInfo.FullName);
}
}
//copy assembly to repo if not found.
if (!string.IsNullOrEmpty(path) && !File.Exists(localRepoPath))
{
if (!Directory.Exists(Path.GetDirectoryName(localRepoPath)))
Directory.CreateDirectory(Path.GetDirectoryName(localRepoPath));
File.Copy(path, localRepoPath);
}
}
}
else
{
path = a.FileInfo.FullName;
}
}
if (a == null || string.IsNullOrEmpty(path))
{
MessageBox.Show("Cannot find or download the artifact " + dll.Name + ", project may not build properly.");
return;
}
}
bool asmNotLoaded = true;
foreach (Assembly asmm in AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies())
{
// compare the assembly name to the filename of the reference to determine if it is a match
// as the location might not be set
// TODO: why do we need to load the assembly?
// added StringComparison.OrdinalIgnoreCase to assembly name compratison in order to avoid errors with
// already loaded assemblies like nunit.framework and NUnit.Framework etc (note this can be reconsidered)
if (asmm.GetName().Name.Equals(Path.GetFileNameWithoutExtension(path), StringComparison.OrdinalIgnoreCase))
{
asm = asmm;
asmNotLoaded = false;
break;
}
}
if (asmNotLoaded)
{
asm = Assembly.ReflectionOnlyLoadFrom(path);
}
SetAssemblyInfoValues(asm.ToString());
//asm = null;
}
string getBinReference(string fileName) {
string path = Path.Combine(this.IncludeFullPath, @"bin\" + Path.GetFileName(fileName));
if (File.Exists(path))
return path;
path = Path.Combine(this.IncludeFullPath, @"bin\debug\" + Path.GetFileName(fileName));
if (File.Exists(path))
return path;
path = Path.Combine(this.IncludeFullPath, @"bin\release\" + Path.GetFileName(fileName));
if (File.Exists(path))
return path;
path = Path.Combine(this.IncludeFullPath, @"obj\debug\" + Path.GetFileName(fileName));
if (File.Exists(path))
return path;
path = Path.Combine(this.IncludeFullPath, @"obj\release\" + Path.GetFileName(fileName));
if (File.Exists(path))
return path;
return string.Empty;
}
public static bool DownloadArtifact(Artifact.Artifact artifact, NPanday.Logging.Logger logger)
{
return downloadArtifactFromRemoteRepository(artifact, artifact.FileInfo.Extension,logger);
}
static bool downloadArtifactFromRemoteRepository(Artifact.Artifact artifact, string ext, NPanday.Logging.Logger logger)
{
try
{
Settings settings = SettingsUtil.ReadSettings(SettingsUtil.GetUserSettingsPath());
if (settings == null || settings.profiles == null)
{
MessageBox.Show("Cannot add reference of "+ artifact.ArtifactId + ", no valid Remote Repository was found that contained the Artifact to be Resolved. Please add a Remote Repository that contains the Unresolved Artifact.");
return false;
}
List<string> activeProfiles = new List<string>();
activeProfiles.AddRange(settings.activeProfiles);
Dictionary<string, string> mirrors = new Dictionary<string, string>();
foreach (Mirror mirror in settings.mirrors)
{
string id = mirror.mirrorOf;
if (id == "external:*") id = "*";
// TODO: support '!' syntax
mirrors.Add(id, mirror.url);
}
Dictionary<string,string> repos = new Dictionary<string,string>();
repos.Add("central", "http://repo1.maven.org/maven2" );
foreach (Profile profile in settings.profiles)
{
if (activeProfiles.Contains(profile.id) && profile.repositories != null)
{
foreach (Repository repo in profile.repositories)
{
repos.Add(repo.id, repo.url);
}
}
}
// TODO: sustain correct ordering from settings.xml
foreach (string id in repos.Keys)
{
string url = repos[id];
if (mirrors.ContainsKey(id))
{
url = mirrors[id];
}
if (mirrors.ContainsKey("*"))
{
url = mirrors["*"];
}
ArtifactContext artifactContext = new ArtifactContext();
if (artifact.Version.Contains("SNAPSHOT"))
{
string newVersion = GetSnapshotVersion(artifact, url, logger);
if (newVersion != null)
{
artifact.RemotePath = artifactContext.GetArtifactRepository().GetRemoteRepositoryPath(artifact, artifact.Version.Replace("SNAPSHOT", newVersion), url, ext);
}
else
{
artifact.RemotePath = artifactContext.GetArtifactRepository().GetRemoteRepositoryPath(artifact, url, ext);
}
}
else
{
artifact.RemotePath = artifactContext.GetArtifactRepository().GetRemoteRepositoryPath(artifact, url, ext);
}
if (downloadArtifact(artifact,logger))
{
return true;
}
}
return false;
}
catch (Exception e)
{
MessageBox.Show("Cannot add reference of " + artifact.ArtifactId + ", an exception occurred trying to download it: " + e.Message );
return false;
}
}
private static string GetSnapshotVersion(NPanday.Artifact.Artifact artifact, string repo, NPanday.Logging.Logger logger)
{
WebClient client = new WebClient();
string timeStampVersion = null;
string metadataPath = repo + "/" + artifact.GroupId.Replace('.','/') + "/" + artifact.ArtifactId;
string snapshot = "<snapshot>";
string metadata = "/maven-metadata.xml";
try
{
metadataPath = metadataPath + "/" + artifact.Version + metadata;
string content = client.DownloadString(metadataPath);
string[] lines = content.Split(new string[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
string timeStamp = null;
string buildNumber = null;
foreach ( string line in lines )
{
int startIndex;
int len;
if (line.Contains("<timestamp>"))
{
startIndex = line.IndexOf("<timestamp>") + "<timestamp>".Length;
len = line.IndexOf("</timestamp>") - startIndex;
timeStamp = line.Substring(startIndex, len);
}
if (line.Contains("<buildNumber>"))
{
startIndex = line.IndexOf("<buildNumber>") + "<buildNumber>".Length;
len = line.IndexOf("</buildNumber>") - startIndex;
buildNumber = line.Substring(startIndex, len);
}
}
if ( timeStamp == null )
{
logger.Log(NPanday.Logging.Level.WARNING, "Timestamp was not specified in maven-metadata.xml - using default snapshot version");
return null;
}
if ( buildNumber == null )
{
logger.Log(NPanday.Logging.Level.WARNING, "Build number was not specified in maven-metadata.xml - using default snapshot version");
return null;
}
timeStampVersion = timeStamp + "-" + buildNumber;
}
catch (Exception e)
{
return null;
}
finally
{
client.Dispose();
}
return timeStampVersion;
}
static bool downloadArtifact(Artifact.Artifact artifact, NPanday.Logging.Logger logger)
{
WebClient client = new WebClient();
bool dirCreated = false;
try
{
if (!artifact.FileInfo.Directory.Exists)
{
artifact.FileInfo.Directory.Create();
dirCreated = true;
}
logger.Log(NPanday.Logging.Level.INFO, string.Format("Download Start: {0} Downloading From {1}\n", DateTime.Now, artifact.RemotePath));
client.DownloadFile(artifact.RemotePath, artifact.FileInfo.FullName);
logger.Log(NPanday.Logging.Level.INFO, string.Format("Download Finished: {0}\n", DateTime.Now));
string artifactDir = GetLocalUacPath(artifact, artifact.FileInfo.Extension);
if (!Directory.Exists(Path.GetDirectoryName(artifactDir)))
{
Directory.CreateDirectory(Path.GetDirectoryName(artifactDir));
}
if (!File.Exists(artifactDir))
{
File.Copy(artifact.FileInfo.FullName, artifactDir);
}
return true;
}
catch (Exception e)
{
if (dirCreated)
{
artifact.FileInfo.Directory.Delete();
}
logger.Log(NPanday.Logging.Level.WARNING, string.Format("Download Failed {0}\n", e.Message));
return false;
}
finally
{
client.Dispose();
}
}
public static string GetLocalUacPath(Artifact.Artifact artifact, string ext)
{
return Path.Combine(Directory.GetParent(SettingsUtil.GetLocalRepositoryPath()).FullName, string.Format(@"uac\gac_msil\{1}\{2}__{0}\{1}{3}", artifact.GroupId, artifact.ArtifactId, artifact.Version, ext));
}
private void SetAssemblyInfoValues(string assemblyInfo)
{
if (!string.IsNullOrEmpty(assemblyInfo))
{
string[] referenceValues = assemblyInfo.Split(',');
this.Name = referenceValues[0].Trim();
if (referenceValues.Length > 1)
{
for (int i = 1; i < referenceValues.Length; i++)
{
if (referenceValues[i].Contains("Version="))
{
this.Version = referenceValues[i].Replace("Version=", "").Trim();
}
else if (referenceValues[i].Contains("PublicKeyToken="))
{
this.PublicKeyToken = referenceValues[i].Replace("PublicKeyToken=", "").Trim();
}
else if (referenceValues[i].Contains("Culture="))
{
this.Culture = referenceValues[i].Replace("Culture=", "").Trim();
}
else if (referenceValues[i].Contains("processorArchitecture="))
{
this.ProcessorArchitecture = referenceValues[i].Replace("processorArchitecture=", "").Trim();
}
}
}
}
}
private void SetAssemblyValuesFromGac(string name)
{
this.Name = name.Split(',')[0].Trim();
string str = GacUtility.GetAssemblyInfo(this.Name, version, processorArchitecture);
SetAssemblyInfoValues(str);
}
#endregion
}
}