Beispiel #1
0
        public AddinScanner(AddinDatabase database, AddinScanResult scanResult, IProgressStatus monitor)
        {
            this.database = database;
            if (!scanResult.CheckOnly) {

                // If there is a local copy of the cecil reflector, use it instead of the one in the gac
                Type t;
                string asmFile = Path.Combine (Path.GetDirectoryName (GetType().Assembly.Location), "Mono.Addins.CecilReflector.dll");
                if (File.Exists (asmFile)) {
                    Assembly asm = Assembly.LoadFrom (asmFile);
                    t = asm.GetType ("Mono.Addins.CecilReflector.Reflector");
                }
                else {
                    string refName = GetType().Assembly.FullName;
                    int i = refName.IndexOf (',');
                    refName = "Mono.Addins.CecilReflector.Reflector, Mono.Addins.CecilReflector" + refName.Substring (i);
                    t = Type.GetType (refName, false);
                }
                if (t != null)
                    reflector = (IAssemblyReflector) Activator.CreateInstance (t);
                else
                    reflector = new DefaultAssemblyReflector ();

                if (monitor.LogLevel > 1)
                    monitor.Log ("Using assembly reflector: " + reflector.GetType ());
                reflector.Initialize (scanResult);
                coreAssembly = reflector.LoadAssembly (GetType().Assembly.Location);
            }
        }
        public AddinScanner(AddinDatabase database, AddinScanResult scanResult, IProgressStatus monitor)
        {
            this.database = database;
            if (!scanResult.CheckOnly)
            {
                string refName = GetType().Assembly.FullName;
                int    i       = refName.IndexOf(',');
                refName = "Mono.Addins.CecilReflector.Reflector, Mono.Addins.CecilReflector" + refName.Substring(i);
                Type t = Type.GetType(refName, false);
                if (t != null)
                {
                    reflector = (IAssemblyReflector)Activator.CreateInstance(t);
                }
                else
                {
                    reflector = new DefaultAssemblyReflector();
                }

                if (monitor.LogLevel > 1)
                {
                    monitor.Log("Using assembly reflector: " + reflector.GetType());
                }
                reflector.Initialize(scanResult);
                coreAssembly = reflector.LoadAssembly(GetType().Assembly.Location);
            }
        }
        void ScanAssemblyAddinHeaders(AddinDescription config, Assembly asm, AddinScanResult scanResult)
        {
            // Get basic add-in information
            AddinAttribute att = (AddinAttribute)Attribute.GetCustomAttribute(asm, typeof(AddinAttribute), false);

            if (att != null)
            {
                if (att.Id.Length > 0)
                {
                    config.LocalId = att.Id;
                }
                if (att.Version.Length > 0)
                {
                    config.Version = att.Version;
                }
                if (att.Namespace.Length > 0)
                {
                    config.Namespace = att.Namespace;
                }
                if (att.Category.Length > 0)
                {
                    config.Category = att.Category;
                }
                config.IsRoot = att is AddinRootAttribute;
            }
        }
        bool ScanAssembly(IProgressStatus monitor, string filePath, AddinScanResult scanResult, out AddinDescription config)
        {
            config = null;

            try {
                Assembly asm = Util.LoadAssemblyForReflection(filePath);

                // Get the config file from the resources, if there is one

                string configFile = null;
                foreach (string res in asm.GetManifestResourceNames())
                {
                    if (res.EndsWith(".addin") || res.EndsWith(".addin.xml"))
                    {
                        configFile = res;
                        break;
                    }
                }

                if (configFile != null)
                {
                    using (Stream s = asm.GetManifestResourceStream(configFile)) {
                        string asmFile = new Uri(asm.CodeBase).LocalPath;
                        config = AddinDescription.Read(s, Path.GetDirectoryName(asmFile));
                    }
                }
                else
                {
                    // On this case, only scan the assembly if it has the Addin attribute.
                    AddinAttribute att = (AddinAttribute)Attribute.GetCustomAttribute(asm, typeof(AddinAttribute), false);
                    if (att == null)
                    {
                        config = null;
                        return(true);
                    }
                    config = new AddinDescription();
                }

                config.BasePath  = Path.GetDirectoryName(filePath);
                config.AddinFile = filePath;

                string rasmFile = Path.GetFileName(filePath);
                if (!config.MainModule.Assemblies.Contains(rasmFile))
                {
                    config.MainModule.Assemblies.Add(rasmFile);
                }

                return(ScanDescription(monitor, config, asm, scanResult));
            }
            catch (Exception ex) {
                // Something went wrong while scanning the assembly. We'll ignore it for now.
                monitor.ReportError("There was an error while scanning assembly: " + filePath, ex);
                return(false);
            }
        }
		public static void AddDependencies (AddinDescription desc, AddinScanResult scanResult)
		{
			// Not implemented in AddinScanResult to avoid making AddinDescription remotable
			foreach (ModuleDescription mod in desc.AllModules) {
				foreach (Dependency dep in mod.Dependencies) {
					AddinDependency adep = dep as AddinDependency;
					if (adep == null) continue;
					string depid = Addin.GetFullId (desc.Namespace, adep.AddinId, adep.Version);
					scanResult.AddAddinToUpdateRelations (depid);
				}
			}
		}
        public void ScanFolderRec(IProgressStatus monitor, string dir, AddinScanResult scanResult)
        {
            ScanFolder(monitor, dir, scanResult);

            if (!Directory.Exists(dir))
            {
                return;
            }

            foreach (string sd in Directory.GetDirectories(dir))
            {
                ScanFolderRec(monitor, sd, scanResult);
            }
        }
        void RegisterFileToScan(IProgressStatus monitor, string file, AddinScanResult scanResult, AddinScanFolderInfo folderInfo)
        {
            if (scanResult.LocateAssembliesOnly)
            {
                return;
            }

            AddinFileInfo finfo = folderInfo.GetAddinFileInfo(file);
            bool          added = false;

            if (finfo != null && File.GetLastWriteTime(file) == finfo.LastScan && !scanResult.RegenerateAllData)
            {
                if (finfo.ScanError)
                {
                    // Always schedule the file for scan if there was an error in a previous scan.
                    // However, don't set ChangesFound=true, in this way if there isn't any other
                    // change in the registry, the file won't be scanned again.
                    scanResult.AddFileToScan(file, folderInfo);
                    added = true;
                }

                if (finfo.AddinId == null || finfo.AddinId.Length == 0)
                {
                    return;
                }
                if (!finfo.IsRoot)
                {
                    if (database.AddinDescriptionExists(finfo.AddinId))
                    {
                        return;
                    }
                }
                else
                {
                    if (database.HostDescriptionExists(finfo.AddinId, file))
                    {
                        return;
                    }
                }
            }

            scanResult.ChangesFound = true;

            if (!scanResult.CheckOnly && !added)
            {
                scanResult.AddFileToScan(file, folderInfo);
            }
        }
        public AddinDescription ScanSingleFile(IProgressStatus monitor, string file, AddinScanResult scanResult)
        {
            AddinDescription config = null;

            if (monitor.LogLevel > 1)
            {
                monitor.Log("Scanning file: " + file);
            }

            monitor.Log("plog:scan:" + file);

            try {
                string ext = Path.GetExtension(file);
                bool   scanSuccessful;

                if (ext == ".dll" || ext == ".exe")
                {
                    scanSuccessful = ScanAssembly(monitor, file, scanResult, out config);
                }
                else
                {
                    scanSuccessful = ScanConfigAssemblies(monitor, file, scanResult, out config);
                }

                if (scanSuccessful && config != null)
                {
                    config.Domain = "global";
                    if (config.Version.Length == 0)
                    {
                        config.Version = "0.0.0.0";
                    }

                    if (config.LocalId.Length == 0)
                    {
                        // Generate an internal id for this add-in
                        config.LocalId = database.GetUniqueAddinId(file, "", config.Namespace, config.Version);
                    }
                }
            }
            catch (Exception ex) {
                monitor.ReportError("Unexpected error while scanning file: " + file, ex);
            } finally {
                monitor.Log("plog:endscan");
            }
            return(config);
        }
Beispiel #9
0
 public static void AddDependencies(AddinDescription desc, AddinScanResult scanResult)
 {
     // Not implemented in AddinScanResult to avoid making AddinDescription remotable
     foreach (ModuleDescription mod in desc.AllModules)
     {
         foreach (Dependency dep in mod.Dependencies)
         {
             AddinDependency adep = dep as AddinDependency;
             if (adep == null)
             {
                 continue;
             }
             string depid = Addin.GetFullId(desc.Namespace, adep.AddinId, adep.Version);
             scanResult.AddAddinToUpdateRelations(depid);
         }
     }
 }
        void RegisterFileToScan(IProgressStatus monitor, string file, AddinScanResult scanResult, AddinScanFolderInfo folderInfo)
        {
            if (scanResult.LocateAssembliesOnly)
            {
                return;
            }

            AddinFileInfo finfo = folderInfo.GetAddinFileInfo(file);
            bool          added = false;

            if (finfo != null && (!finfo.IsAddin || finfo.Domain == folderInfo.GetDomain(finfo.IsRoot)) && File.GetLastWriteTime(file) == finfo.LastScan && !scanResult.RegenerateAllData)
            {
                if (finfo.ScanError)
                {
                    // Always schedule the file for scan if there was an error in a previous scan.
                    // However, don't set ChangesFound=true, in this way if there isn't any other
                    // change in the registry, the file won't be scanned again.
                    scanResult.AddFileToScan(file, folderInfo);
                    added = true;
                }

                if (!finfo.IsAddin)
                {
                    return;
                }

                if (database.AddinDescriptionExists(finfo.Domain, finfo.AddinId))
                {
                    // It is an add-in and it has not changed. Paths in the ignore list
                    // are still valid, so they can be used.
                    if (finfo.IgnorePaths != null)
                    {
                        scanResult.AddPathsToIgnore(finfo.IgnorePaths);
                    }
                    return;
                }
            }

            scanResult.ChangesFound = true;

            if (!scanResult.CheckOnly && !added)
            {
                scanResult.AddFileToScan(file, folderInfo);
            }
        }
        bool ScanConfigAssemblies(IProgressStatus monitor, string filePath, AddinScanResult scanResult, out AddinDescription config)
        {
            config = null;

            try {
                string basePath = Path.GetDirectoryName(filePath);

                config           = AddinDescription.Read(filePath);
                config.BasePath  = basePath;
                config.AddinFile = filePath;

                return(ScanDescription(monitor, config, null, scanResult));
            }
            catch (Exception ex) {
                // Something went wrong while scanning the assembly. We'll ignore it for now.
                monitor.ReportError("There was an error while scanning add-in: " + filePath, ex);
                return(false);
            }
        }
Beispiel #12
0
        void ScanAssemblyAddinHeaders(IAssemblyReflector reflector, AddinDescription config, object asm, AddinScanResult scanResult)
        {
            // Get basic add-in information
            AddinAttribute att = (AddinAttribute) reflector.GetCustomAttribute (asm, typeof(AddinAttribute), false);
            if (att != null) {
                if (att.Id.Length > 0)
                    config.LocalId = att.Id;
                if (att.Version.Length > 0)
                    config.Version = att.Version;
                if (att.Namespace.Length > 0)
                    config.Namespace = att.Namespace;
                if (att.Category.Length > 0)
                    config.Category = att.Category;
                if (att.CompatVersion.Length > 0)
                    config.CompatVersion = att.CompatVersion;
                if (att.Url.Length > 0)
                    config.Url = att.Url;
                config.IsRoot = att is AddinRootAttribute;
                config.EnabledByDefault = att.EnabledByDefault;
                config.Flags = att.Flags;
            }

            // Author attributes

            object[] atts = reflector.GetCustomAttributes (asm, typeof(AddinAuthorAttribute), false);
            foreach (AddinAuthorAttribute author in atts) {
                if (config.Author.Length == 0)
                    config.Author = author.Name;
                else
                    config.Author += ", " + author.Name;
            }

            // Name

            atts = reflector.GetCustomAttributes (asm, typeof(AddinNameAttribute), false);
            foreach (AddinNameAttribute at in atts) {
                if (string.IsNullOrEmpty (at.Locale))
                    config.Name = at.Name;
                else
                    config.Properties.SetPropertyValue ("Name", at.Name, at.Locale);
            }

            // Description

            object catt = reflector.GetCustomAttribute (asm, typeof(AssemblyDescriptionAttribute), false);
            if (catt != null && config.Description.Length == 0)
                config.Description = ((AssemblyDescriptionAttribute)catt).Description;

            atts = reflector.GetCustomAttributes (asm, typeof(AddinDescriptionAttribute), false);
            foreach (AddinDescriptionAttribute at in atts) {
                if (string.IsNullOrEmpty (at.Locale))
                    config.Description = at.Description;
                else
                    config.Properties.SetPropertyValue ("Description", at.Description, at.Locale);
            }

            // Copyright

            catt = reflector.GetCustomAttribute (asm, typeof(AssemblyCopyrightAttribute), false);
            if (catt != null && config.Copyright.Length == 0)
                config.Copyright = ((AssemblyCopyrightAttribute)catt).Copyright;

            // Localizer

            AddinLocalizerGettextAttribute locat = (AddinLocalizerGettextAttribute) reflector.GetCustomAttribute (asm, typeof(AddinLocalizerGettextAttribute), false);
            if (locat != null) {
                ExtensionNodeDescription node = new ExtensionNodeDescription ();
                if (!string.IsNullOrEmpty (locat.Catalog))
                    node.SetAttribute ("catalog", locat.Catalog);
                if (!string.IsNullOrEmpty (locat.Location))
                    node.SetAttribute ("location", locat.Catalog);
                config.Localizer = node;
            }

            // Optional modules

            atts = reflector.GetCustomAttributes (asm, typeof(AddinModuleAttribute), false);
            foreach (AddinModuleAttribute mod in atts) {
                if (mod.AssemblyFile.Length > 0) {
                    ModuleDescription module = new ModuleDescription ();
                    module.Assemblies.Add (mod.AssemblyFile);
                    config.OptionalModules.Add (module);
                }
            }
        }
        void ReportReflectionException(IProgressStatus monitor, Exception ex, AddinDescription config, AddinScanResult scanResult)
        {
            scanResult.AddFileToWithFailure(config.AddinFile);
            monitor.ReportWarning("[" + config.AddinId + "] Could not load some add-in assemblies: " + ex.Message);
            if (monitor.LogLevel <= 1)
            {
                return;
            }

            ReflectionTypeLoadException rex = ex as ReflectionTypeLoadException;

            if (rex != null)
            {
                foreach (Exception e in rex.LoaderExceptions)
                {
                    monitor.Log("Load exception: " + e);
                }
            }
        }
Beispiel #14
0
        void RegisterFileToScan(IProgressStatus monitor, string file, AddinScanResult scanResult, AddinScanFolderInfo folderInfo)
        {
            if (scanResult.LocateAssembliesOnly)
                return;

            AddinFileInfo finfo = folderInfo.GetAddinFileInfo (file);
            bool added = false;

            if (finfo != null && (!finfo.IsAddin || finfo.Domain == folderInfo.GetDomain (finfo.IsRoot)) && fs.GetLastWriteTime (file) == finfo.LastScan && !scanResult.RegenerateAllData) {
                if (finfo.ScanError) {
                    // Always schedule the file for scan if there was an error in a previous scan.
                    // However, don't set ChangesFound=true, in this way if there isn't any other
                    // change in the registry, the file won't be scanned again.
                    scanResult.AddFileToScan (file, folderInfo);
                    added = true;
                }

                if (!finfo.IsAddin)
                    return;

                if (database.AddinDescriptionExists (finfo.Domain, finfo.AddinId)) {
                    // It is an add-in and it has not changed. Paths in the ignore list
                    // are still valid, so they can be used.
                    if (finfo.IgnorePaths != null)
                        scanResult.AddPathsToIgnore (finfo.IgnorePaths);
                    return;
                }
            }

            scanResult.ChangesFound = true;

            if (!scanResult.CheckOnly && !added)
                scanResult.AddFileToScan (file, folderInfo);
        }
Beispiel #15
0
        void ReportReflectionException(IProgressStatus monitor, Exception ex, AddinDescription config, AddinScanResult scanResult)
        {
            scanResult.AddFileToWithFailure (config.AddinFile);
            monitor.ReportWarning ("[" + config.AddinId + "] Could not load some add-in assemblies: " + ex.Message);
            if (monitor.LogLevel <= 1)
                return;

            ReflectionTypeLoadException rex = ex as ReflectionTypeLoadException;
            if (rex != null) {
                foreach (Exception e in rex.LoaderExceptions)
                    monitor.Log ("Load exception: " + e);
            }
        }
Beispiel #16
0
        public void ScanFolderRec(IProgressStatus monitor, string dir, string domain, AddinScanResult scanResult)
        {
            ScanFolder (monitor, dir, domain, scanResult);

            if (!fs.DirectoryExists (dir))
                return;

            foreach (string sd in fs.GetDirectories (dir))
                ScanFolderRec (monitor, sd, domain, scanResult);
        }
Beispiel #17
0
        public void UpdateDeletedAddins(IProgressStatus monitor, AddinScanFolderInfo folderInfo, AddinScanResult scanResult)
        {
            ArrayList missing = folderInfo.GetMissingAddins (fs);
            if (missing.Count > 0) {
                if (fs.DirectoryExists (folderInfo.Folder))
                    scanResult.RegisterModifiedFolderInfo (folderInfo);
                scanResult.ChangesFound = true;
                if (scanResult.CheckOnly)
                    return;

                foreach (AddinFileInfo info in missing) {
                    database.UninstallAddin (monitor, info.Domain, info.AddinId, info.File, scanResult);
                }
            }
        }
Beispiel #18
0
 internal void ScanFolders(IProgressStatus monitor, string currentDomain, string folderToScan, StringCollection filesToIgnore)
 {
     AddinScanResult res = new AddinScanResult ();
     res.Domain = currentDomain;
     res.AddPathsToIgnore (filesToIgnore);
     ScanFolders (monitor, res);
 }
Beispiel #19
0
        public void ScanFile(IProgressStatus monitor, string file, AddinScanFolderInfo folderInfo, AddinScanResult scanResult)
        {
            if (scanResult.IgnorePath (file)) {
                // The file must be ignored. Maybe it caused a crash in a previous scan, or it
                // might be included by a .addin file (in which case it will be scanned when processing
                // the .addin file).
                folderInfo.SetLastScanTime (file, null, false, fs.GetLastWriteTime (file), true);
                return;
            }

            if (monitor.LogLevel > 1)
                monitor.Log ("Scanning file: " + file);

            // Log the file to be scanned, so in case of a process crash the main process
            // will know what crashed
            monitor.Log ("plog:scan:" + file);

            string scannedAddinId = null;
            bool scannedIsRoot = false;
            bool scanSuccessful = false;
            AddinDescription config = null;

            try {
                string ext = Path.GetExtension (file).ToLower ();

                if (ext == ".dll" || ext == ".exe")
                    scanSuccessful = ScanAssembly (monitor, file, scanResult, out config);
                else
                    scanSuccessful = ScanConfigAssemblies (monitor, file, scanResult, out config);

                if (config != null) {

                    AddinFileInfo fi = folderInfo.GetAddinFileInfo (file);

                    // If version is not specified, make up one
                    if (config.Version.Length == 0) {
                        config.Version = "0.0.0.0";
                    }

                    if (config.LocalId.Length == 0) {
                        // Generate an internal id for this add-in
                        config.LocalId = database.GetUniqueAddinId (file, (fi != null ? fi.AddinId : null), config.Namespace, config.Version);
                        config.HasUserId = false;
                    }

                    // Check errors in the description
                    StringCollection errors = config.Verify (fs);

                    if (database.IsGlobalRegistry && config.AddinId.IndexOf ('.') == -1) {
                        errors.Add ("Add-ins registered in the global registry must have a namespace.");
                    }

                    if (errors.Count > 0) {
                        scanSuccessful = false;
                        monitor.ReportError ("Errors found in add-in '" + file + ":", null);
                        foreach (string err in errors)
                            monitor.ReportError (err, null);
                    }

                    // Make sure all extensions sets are initialized with the correct add-in id

                    config.SetExtensionsAddinId (config.AddinId);

                    scanResult.ChangesFound = true;

                    // If the add-in already existed, try to reuse the relation data it had.
                    // Also, the dependencies of the old add-in need to be re-analized

                    AddinDescription existingDescription = null;
                    bool res = database.GetAddinDescription (monitor, folderInfo.Domain, config.AddinId, config.AddinFile, out existingDescription);

                    // If we can't get information about the old assembly, just regenerate all relation data
                    if (!res)
                        scanResult.RegenerateRelationData = true;

                    string replaceFileName = null;

                    if (existingDescription != null) {
                        // Reuse old relation data
                        config.MergeExternalData (existingDescription);
                        Util.AddDependencies (existingDescription, scanResult);
                        replaceFileName = existingDescription.FileName;
                    }

                    // If the scanned file results in an add-in version different from the one obtained from
                    // previous scans, the old add-in needs to be uninstalled.
                    if (fi != null && fi.IsAddin && fi.AddinId != config.AddinId) {
                        database.UninstallAddin (monitor, folderInfo.Domain, fi.AddinId, fi.File, scanResult);

                        // If the add-in version has changed, regenerate everything again since old data can't be reused
                        if (Addin.GetIdName (fi.AddinId) == Addin.GetIdName (config.AddinId))
                            scanResult.RegenerateRelationData = true;
                    }

                    // If a description could be generated, save it now (if the scan was successful)
                    if (scanSuccessful) {

                        // Assign the domain
                        if (config.IsRoot) {
                            if (folderInfo.RootsDomain == null) {
                                if (scanResult.Domain != null && scanResult.Domain != AddinDatabase.UnknownDomain && scanResult.Domain != AddinDatabase.GlobalDomain)
                                    folderInfo.RootsDomain = scanResult.Domain;
                                else
                                    folderInfo.RootsDomain = database.GetUniqueDomainId ();
                            }
                            config.Domain = folderInfo.RootsDomain;
                        } else
                            config.Domain = folderInfo.Domain;

                        if (config.IsRoot && scanResult.HostIndex != null) {
                            // If the add-in is a root, register its assemblies
                            foreach (string f in config.MainModule.Assemblies) {
                                string asmFile = Path.Combine (config.BasePath, f);
                                scanResult.HostIndex.RegisterAssembly (asmFile, config.AddinId, config.AddinFile, config.Domain);
                            }
                        }

                        // Finally save

                        if (database.SaveDescription (monitor, config, replaceFileName)) {
                            // The new dependencies also have to be updated
                            Util.AddDependencies (config, scanResult);
                            scanResult.AddAddinToUpdate (config.AddinId);
                            scannedAddinId = config.AddinId;
                            scannedIsRoot = config.IsRoot;
                            return;
                        }
                    }
                }
            }
            catch (Exception ex) {
                monitor.ReportError ("Unexpected error while scanning file: " + file, ex);
            }
            finally {
                AddinFileInfo ainfo = folderInfo.SetLastScanTime (file, scannedAddinId, scannedIsRoot, fs.GetLastWriteTime (file), !scanSuccessful);

                if (scanSuccessful && config != null) {
                    // Update the ignore list in the folder info object. To be used in the next scan
                    foreach (string df in config.AllIgnorePaths) {
                        string path = Path.Combine (config.BasePath, df);
                        ainfo.AddPathToIgnore (Path.GetFullPath (path));
                    }
                }

                monitor.Log ("plog:endscan");
            }
        }
        public void ScanFile(IProgressStatus monitor, string file, AddinScanFolderInfo folderInfo, AddinScanResult scanResult)
        {
            if (scanResult.IgnorePath(file))
            {
                // The file must be ignored. Maybe it caused a crash in a previous scan, or it
                // might be included by a .addin file (in which case it will be scanned when processing
                // the .addin file).
                folderInfo.SetLastScanTime(file, null, false, File.GetLastWriteTime(file), true);
                return;
            }

            if (monitor.LogLevel > 1)
            {
                monitor.Log("Scanning file: " + file);
            }

            // Log the file to be scanned, so in case of a process crash the main process
            // will know what crashed
            monitor.Log("plog:scan:" + file);

            string           scannedAddinId = null;
            bool             scannedIsRoot  = false;
            bool             scanSuccessful = false;
            AddinDescription config         = null;

            try {
                string ext = Path.GetExtension(file);

                if (ext == ".dll" || ext == ".exe")
                {
                    scanSuccessful = ScanAssembly(monitor, file, scanResult, out config);
                }
                else
                {
                    scanSuccessful = ScanConfigAssemblies(monitor, file, scanResult, out config);
                }

                if (config != null)
                {
                    AddinFileInfo fi = folderInfo.GetAddinFileInfo(file);

                    // If version is not specified, make up one
                    if (config.Version.Length == 0)
                    {
                        config.Version = "0.0.0.0";
                    }

                    if (config.LocalId.Length == 0)
                    {
                        // Generate an internal id for this add-in
                        config.LocalId   = database.GetUniqueAddinId(file, (fi != null ? fi.AddinId : null), config.Namespace, config.Version);
                        config.HasUserId = false;
                    }

                    // Check errors in the description
                    StringCollection errors = config.Verify();

                    if (database.IsGlobalRegistry && config.AddinId.IndexOf('.') == -1)
                    {
                        errors.Add("Add-ins registered in the global registry must have a namespace.");
                    }

                    if (errors.Count > 0)
                    {
                        scanSuccessful = false;
                        monitor.ReportError("Errors found in add-in '" + file + ":", null);
                        foreach (string err in errors)
                        {
                            monitor.ReportError(err, null);
                        }
                    }

                    // Make sure all extensions sets are initialized with the correct add-in id

                    config.SetExtensionsAddinId(config.AddinId);

                    scanResult.ChangesFound = true;

                    // If the add-in already existed, try to reuse the relation data it had.
                    // Also, the dependencies of the old add-in need to be re-analized

                    AddinDescription existingDescription = null;
                    bool             res = database.GetAddinDescription(monitor, folderInfo.Domain, config.AddinId, out existingDescription);

                    // If we can't get information about the old assembly, just regenerate all relation data
                    if (!res)
                    {
                        scanResult.RegenerateRelationData = true;
                    }

                    string replaceFileName = null;

                    if (existingDescription != null)
                    {
                        // Reuse old relation data
                        config.MergeExternalData(existingDescription);
                        Util.AddDependencies(existingDescription, scanResult);
                        replaceFileName = existingDescription.FileName;
                    }

                    // If the scanned file results in an add-in version different from the one obtained from
                    // previous scans, the old add-in needs to be uninstalled.
                    if (fi != null && fi.IsAddin && fi.AddinId != config.AddinId)
                    {
                        database.UninstallAddin(monitor, folderInfo.Domain, fi.AddinId, scanResult);

                        // If the add-in version has changed, regenerate everything again since old data can't be reused
                        if (Addin.GetIdName(fi.AddinId) == Addin.GetIdName(config.AddinId))
                        {
                            scanResult.RegenerateRelationData = true;
                        }
                    }

                    // If a description could be generated, save it now (if the scan was successful)
                    if (scanSuccessful)
                    {
                        // Assign the domain
                        if (config.IsRoot)
                        {
                            if (folderInfo.RootsDomain == null)
                            {
                                if (scanResult.Domain != null && scanResult.Domain != AddinDatabase.UnknownDomain && scanResult.Domain != AddinDatabase.GlobalDomain)
                                {
                                    folderInfo.RootsDomain = scanResult.Domain;
                                }
                                else
                                {
                                    folderInfo.RootsDomain = database.GetUniqueDomainId();
                                }
                            }
                            config.Domain = folderInfo.RootsDomain;
                        }
                        else
                        {
                            config.Domain = folderInfo.Domain;
                        }

                        if (config.IsRoot && scanResult.HostIndex != null)
                        {
                            // If the add-in is a root, register its assemblies
                            foreach (string f in config.MainModule.Assemblies)
                            {
                                string asmFile = Path.Combine(config.BasePath, f);
                                scanResult.HostIndex.RegisterAssembly(asmFile, config.AddinId, config.AddinFile, config.Domain);
                            }
                        }

                        // Finally save

                        if (database.SaveDescription(monitor, config, replaceFileName))
                        {
                            // The new dependencies also have to be updated
                            Util.AddDependencies(config, scanResult);
                            scanResult.AddAddinToUpdateRelations(config.AddinId);
                            scannedAddinId = config.AddinId;
                            scannedIsRoot  = config.IsRoot;
                            return;
                        }
                    }
                }
            }
            catch (Exception ex) {
                monitor.ReportError("Unexpected error while scanning file: " + file, ex);
            }
            finally {
                AddinFileInfo ainfo = folderInfo.SetLastScanTime(file, scannedAddinId, scannedIsRoot, File.GetLastWriteTime(file), !scanSuccessful);

                if (scanSuccessful && config != null)
                {
                    // Update the ignore list in the folder info object. To be used in the next scan
                    foreach (string df in config.AllIgnorePaths)
                    {
                        string path = Path.Combine(config.BasePath, df);
                        ainfo.AddPathToIgnore(Util.GetFullPath(path));
                    }
                }

                monitor.Log("plog:endscan");
            }
        }
 public AddinRegistryUpdater(AddinDatabase database, AddinScanResult scanResult) : base(database)
 {
     this.database   = database;
     this.scanResult = scanResult;
     ScanContext     = scanResult.ScanContext;
 }
        public void ScanAddinsFile(IProgressStatus monitor, string file, AddinScanResult scanResult)
        {
            XmlTextReader    r                      = null;
            StringCollection directories            = new StringCollection();
            StringCollection directoriesWithSubdirs = new StringCollection();

            try {
                r = new XmlTextReader(new StreamReader(file));
                r.MoveToContent();
                if (r.IsEmptyElement)
                {
                    return;
                }
                r.ReadStartElement();
                r.MoveToContent();
                while (r.NodeType != XmlNodeType.EndElement)
                {
                    if (r.NodeType == XmlNodeType.Element && r.LocalName == "Directory")
                    {
                        string subs = r.GetAttribute("include-subdirs");
                        string path = r.ReadElementString().Trim();
                        if (path.Length > 0)
                        {
                            if (subs == "true")
                            {
                                directoriesWithSubdirs.Add(path);
                            }
                            else
                            {
                                directories.Add(path);
                            }
                        }
                    }
                    else
                    {
                        r.Skip();
                    }
                    r.MoveToContent();
                }
            } catch (Exception ex) {
                monitor.ReportError("Could not process addins file: " + file, ex);
                return;
            } finally {
                if (r != null)
                {
                    r.Close();
                }
            }
            foreach (string d in directories)
            {
                string dir = d;
                if (!Path.IsPathRooted(dir))
                {
                    dir = Path.Combine(Path.GetDirectoryName(file), dir);
                }
                ScanFolder(monitor, dir, scanResult);
            }
            foreach (string d in directoriesWithSubdirs)
            {
                string dir = d;
                if (!Path.IsPathRooted(dir))
                {
                    dir = Path.Combine(Path.GetDirectoryName(file), dir);
                }
                ScanFolderRec(monitor, dir, scanResult);
            }
        }
        public void ScanFile(IProgressStatus monitor, string file, AddinScanFolderInfo folderInfo, AddinScanResult scanResult)
        {
            if (monitor.VerboseLog)
            {
                monitor.Log("Scanning file: " + file);
            }

            string scannedAddinId = null;
            bool   scannedIsRoot  = false;
            bool   scanSuccessful = false;

            try {
                string           ext    = Path.GetExtension(file);
                AddinDescription config = null;

                if (ext == ".dll" || ext == ".exe")
                {
                    scanSuccessful = ScanAssembly(monitor, file, scanResult, out config);
                }
                else
                {
                    scanSuccessful = ScanConfigAssemblies(monitor, file, scanResult, out config);
                }

                if (config != null)
                {
                    AddinFileInfo fi = folderInfo.GetAddinFileInfo(file);

                    // If version is not specified, make up one
                    if (config.Version.Length == 0)
                    {
                        config.Version = "0.0.0.0";
                    }

                    if (config.LocalId.Length == 0)
                    {
                        // Generate an internal id for this add-in
                        config.LocalId   = database.GetUniqueAddinId(file, (fi != null ? fi.AddinId : null), config.Namespace, config.Version);
                        config.HasUserId = false;
                    }

                    // Check errors in the description
                    StringCollection errors = config.Verify();

                    if (database.IsGlobalRegistry && config.AddinId.IndexOf('.') == -1)
                    {
                        errors.Add("Add-ins registered in the global registry must have a namespace.");
                    }

                    if (errors.Count > 0)
                    {
                        scanSuccessful = false;
                        monitor.ReportError("Errors found in add-in '" + file + ":", null);
                        foreach (string err in errors)
                        {
                            monitor.ReportError(err, null);
                        }
                    }

                    // Make sure all extensions sets are initialized with the correct add-in id

                    config.SetExtensionsAddinId(config.AddinId);

                    scanResult.ChangesFound = true;

                    // If the add-in already existed, try to reuse the relation data it had.
                    // Also, the dependencies of the old add-in need to be re-analized

                    AddinDescription existingDescription = null;
                    bool             res;

                    if (config.IsRoot)
                    {
                        res = database.GetHostDescription(monitor, config.AddinId, config.AddinFile, out existingDescription);
                    }
                    else
                    {
                        res = database.GetAddinDescription(monitor, config.AddinId, out existingDescription);
                    }

                    // If we can't get information about the old assembly, just regenerate all relation data
                    if (!res)
                    {
                        scanResult.RegenerateRelationData = true;
                    }

                    string replaceFileName = null;

                    if (existingDescription != null)
                    {
                        // Reuse old relation data
                        config.MergeExternalData(existingDescription);
                        Util.AddDependencies(existingDescription, scanResult);
                        replaceFileName = existingDescription.FileName;
                    }

                    // If the scanned file results in an add-in version different from the one obtained from
                    // previous scans, the old add-in needs to be uninstalled.
                    if (fi != null && fi.AddinId != null && fi.AddinId != config.AddinId)
                    {
                        if (fi.IsRoot)
                        {
                            database.UninstallRootAddin(monitor, fi.AddinId, file, scanResult);
                        }
                        else
                        {
                            database.UninstallAddin(monitor, fi.AddinId, scanResult);
                        }

                        // If the add-in version has changed, regenerate everything again since old data can't be reused
                        if (Addin.GetIdName(fi.AddinId) == Addin.GetIdName(config.AddinId))
                        {
                            scanResult.RegenerateRelationData = true;
                        }
                    }

                    // If a description could be generated, save it now (if the scan was successful)
                    if (scanSuccessful)
                    {
                        if (database.SaveDescription(monitor, config, replaceFileName))
                        {
                            // The new dependencies also have to be updated
                            Util.AddDependencies(config, scanResult);
                            scanResult.AddAddinToUpdateRelations(config.AddinId);
                            scannedAddinId = config.AddinId;
                            scannedIsRoot  = config.IsRoot;
                            return;
                        }
                    }
                }
            }
            catch (Exception ex) {
                monitor.ReportError("Unexpected error while scanning file: " + file, ex);
            }
            finally {
                folderInfo.SetLastScanTime(file, scannedAddinId, scannedIsRoot, File.GetLastWriteTime(file), !scanSuccessful);
            }
        }
        public void ScanAddinsFile(IProgressStatus monitor, string file, string domain, AddinScanResult scanResult)
        {
            XmlTextReader r                      = null;
            ArrayList     directories            = new ArrayList();
            ArrayList     directoriesWithSubdirs = new ArrayList();
            string        basePath               = Path.GetDirectoryName(file);

            try {
                r = new XmlTextReader(new StreamReader(file));
                r.MoveToContent();
                if (r.IsEmptyElement)
                {
                    return;
                }
                r.ReadStartElement();
                r.MoveToContent();
                while (r.NodeType != XmlNodeType.EndElement)
                {
                    if (r.NodeType == XmlNodeType.Element && r.LocalName == "Directory")
                    {
                        string subs = r.GetAttribute("include-subdirs");
                        string sdom;
                        string share = r.GetAttribute("shared");
                        if (share == "true")
                        {
                            sdom = AddinDatabase.GlobalDomain;
                        }
                        else if (share == "false")
                        {
                            sdom = null;
                        }
                        else
                        {
                            sdom = domain;                             // Inherit the domain
                        }
                        string path = r.ReadElementString().Trim();
                        if (path.Length > 0)
                        {
                            path = Util.NormalizePath(path);
                            if (subs == "true")
                            {
                                directoriesWithSubdirs.Add(new string[] { path, sdom });
                            }
                            else
                            {
                                directories.Add(new string[] { path, sdom });
                            }
                        }
                    }
                    else if (r.NodeType == XmlNodeType.Element && r.LocalName == "GacAssembly")
                    {
                        string aname = r.ReadElementString().Trim();
                        if (aname.Length > 0)
                        {
                            aname = Util.NormalizePath(aname);
                            aname = Util.GetGacPath(aname);
                            if (aname != null)
                            {
                                // Gac assemblies always use the global domain
                                directories.Add(new string[] { aname, AddinDatabase.GlobalDomain });
                            }
                        }
                    }
                    else if (r.NodeType == XmlNodeType.Element && r.LocalName == "Exclude")
                    {
                        string path = r.ReadElementString().Trim();
                        if (path.Length > 0)
                        {
                            path = Util.NormalizePath(path);
                            if (!Path.IsPathRooted(path))
                            {
                                path = Path.Combine(basePath, path);
                            }
                            scanResult.AddPathToIgnore(Util.GetFullPath(path));
                        }
                    }
                    else
                    {
                        r.Skip();
                    }
                    r.MoveToContent();
                }
            } catch (Exception ex) {
                monitor.ReportError("Could not process addins file: " + file, ex);
                return;
            } finally {
                if (r != null)
                {
                    r.Close();
                }
            }

            foreach (string[] d in directories)
            {
                string dir = d[0];
                if (!Path.IsPathRooted(dir))
                {
                    dir = Path.Combine(basePath, dir);
                }
                ScanFolder(monitor, dir, d[1], scanResult);
            }
            foreach (string[] d in directoriesWithSubdirs)
            {
                string dir = d[0];
                if (!Path.IsPathRooted(dir))
                {
                    dir = Path.Combine(basePath, dir);
                }
                ScanFolderRec(monitor, dir, d[1], scanResult);
            }
        }
        public void UpdateDeletedAddins(IProgressStatus monitor, AddinScanFolderInfo folderInfo, AddinScanResult scanResult)
        {
            ArrayList missing = folderInfo.GetMissingAddins();

            if (missing.Count > 0)
            {
                if (Directory.Exists(folderInfo.Folder))
                {
                    scanResult.ModifiedFolderInfos.Add(folderInfo);
                }
                scanResult.ChangesFound = true;
                if (scanResult.CheckOnly)
                {
                    return;
                }

                foreach (AddinFileInfo info in missing)
                {
                    if (info.IsRoot)
                    {
                        database.UninstallRootAddin(monitor, info.AddinId, info.File, scanResult);
                    }
                    else
                    {
                        database.UninstallAddin(monitor, info.AddinId, scanResult);
                    }
                }
            }
        }
        bool ScanDescription(IProgressStatus monitor, AddinDescription config, Assembly rootAssembly, AddinScanResult scanResult)
        {
            // First of all scan the main module

            ArrayList assemblies           = new ArrayList();
            ArrayList asmFiles             = new ArrayList();
            ArrayList hostExtensionClasses = new ArrayList();

            try {
                // Add all data files to the ignore file list. It avoids scanning assemblies
                // which are included as 'data' in an add-in.
                foreach (string df in config.AllFiles)
                {
                    string file = Path.Combine(config.BasePath, df);
                    scanResult.AddPathToIgnore(Util.GetFullPath(file));
                }
                foreach (string df in config.AllIgnorePaths)
                {
                    string path = Path.Combine(config.BasePath, df);
                    scanResult.AddPathToIgnore(Util.GetFullPath(path));
                }

                foreach (string s in config.MainModule.Assemblies)
                {
                    string asmFile = Path.Combine(config.BasePath, s);
                    asmFiles.Add(asmFile);
                    object asm = reflector.LoadAssembly(asmFile);
                    assemblies.Add(asm);
                    scanResult.AddPathToIgnore(Util.GetFullPath(asmFile));
                }

                foreach (object asm in assemblies)
                {
                    ScanAssemblyAddinHeaders(config, asm, scanResult);
                }

                // The add-in id and version must be already assigned at this point

                // Clean host data from the index. New data will be added.
                if (scanResult.HostIndex != null)
                {
                    scanResult.HostIndex.RemoveHostData(config.AddinId, config.AddinFile);
                }

                foreach (object asm in assemblies)
                {
                    ScanAssemblyContents(config, asm, hostExtensionClasses, scanResult);
                }
            } catch (Exception ex) {
                ReportReflectionException(monitor, ex, config, scanResult);
                return(false);
            }

            foreach (object t in hostExtensionClasses)
            {
                RegisterHostTypeNode(config, t, assemblies);
            }

            // Extension node types may have child nodes declared as attributes. Find them.

            Hashtable internalNodeSets = new Hashtable();

            ArrayList setsCopy = new ArrayList();

            setsCopy.AddRange(config.ExtensionNodeSets);
            foreach (ExtensionNodeSet eset in setsCopy)
            {
                ScanNodeSet(config, eset, assemblies, internalNodeSets);
            }

            foreach (ExtensionPoint ep in config.ExtensionPoints)
            {
                ScanNodeSet(config, ep.NodeSet, assemblies, internalNodeSets);
            }

            // Now scan all modules

            if (!config.IsRoot)
            {
                foreach (ModuleDescription mod in config.OptionalModules)
                {
                    try {
                        assemblies.Clear();
                        asmFiles.Clear();
                        foreach (string s in mod.Assemblies)
                        {
                            string asmFile = Path.Combine(config.BasePath, s);
                            asmFiles.Add(asmFile);
                            object asm = reflector.LoadAssembly(asmFile);
                            assemblies.Add(asm);
                            scanResult.AddPathToIgnore(Util.GetFullPath(asmFile));
                        }
                        foreach (object asm in assemblies)
                        {
                            ScanAssemblyContents(config, asm, null, scanResult);
                        }
                    } catch (Exception ex) {
                        ReportReflectionException(monitor, ex, config, scanResult);
                    }
                }
            }

            config.StoreFileInfo();
            return(true);
        }
Beispiel #27
0
        public void ParseAddin(IProgressStatus progressStatus, string domain, string file, string outFile, bool inProcess)
        {
            if (!inProcess) {
                ISetupHandler setup = GetSetupHandler ();
                setup.GetAddinDescription (progressStatus, registry, Path.GetFullPath (file), outFile);
                return;
            }

            using (fileDatabase.LockRead ())
            {
                // First of all, check if the file belongs to a registered add-in
                AddinScanFolderInfo finfo;
                if (GetFolderInfoForPath (progressStatus, Path.GetDirectoryName (file), out finfo) && finfo != null) {
                    AddinFileInfo afi = finfo.GetAddinFileInfo (file);
                    if (afi != null && afi.IsAddin) {
                        AddinDescription adesc;
                        GetAddinDescription (progressStatus, afi.Domain, afi.AddinId, file, out adesc);
                        if (adesc != null)
                            adesc.Save (outFile);
                        return;
                    }
                }

                AddinScanResult sr = new AddinScanResult ();
                sr.Domain = domain;
                AddinScanner scanner = new AddinScanner (this, sr, progressStatus);

                SingleFileAssemblyResolver res = new SingleFileAssemblyResolver (progressStatus, registry, scanner);
                ResolveEventHandler resolver = new ResolveEventHandler (res.Resolve);

                EventInfo einfo = typeof(AppDomain).GetEvent ("ReflectionOnlyAssemblyResolve");

                try {
                    AppDomain.CurrentDomain.AssemblyResolve += resolver;
                    if (einfo != null) einfo.AddEventHandler (AppDomain.CurrentDomain, resolver);

                    AddinDescription desc = scanner.ScanSingleFile (progressStatus, file, sr);
                    if (desc != null) {
                        // Reset the xml doc so that it is not reused when saving. We want a brand new document
                        desc.ResetXmlDoc ();
                        desc.Save (outFile);
                    }
                }
                finally {
                    AppDomain.CurrentDomain.AssemblyResolve -= resolver;
                    if (einfo != null) einfo.RemoveEventHandler (AppDomain.CurrentDomain, resolver);
                }
            }
        }
        public void ScanFolder(IProgressStatus monitor, string path, AddinScanResult scanResult)
        {
            path = Util.GetFullPath(path);

            // Avoid folders including each other
            if (!scanResult.VisitFolder(path))
            {
                return;
            }

            if (monitor.VerboseLog && !scanResult.LocateAssembliesOnly)
            {
                monitor.Log("Checking: " + path);
            }

            AddinScanFolderInfo folderInfo;

            if (!database.GetFolderInfoForPath(monitor, path, out folderInfo))
            {
                // folderInfo file was corrupt.
                // Just in case, we are going to regenerate all relation data.
                if (!Directory.Exists(path))
                {
                    scanResult.RegenerateRelationData = true;
                }
            }
            else
            {
                if (folderInfo == null && !Directory.Exists(path))
                {
                    return;
                }
            }

            if (folderInfo == null)
            {
                folderInfo = new AddinScanFolderInfo(path);
            }

            if (Directory.Exists(path))
            {
                foreach (string file in Directory.GetFiles(path))
                {
                    if (file.EndsWith(".addin.xml"))
                    {
                        RegisterFileToScan(monitor, file, scanResult, folderInfo);
                        continue;
                    }
                    switch (Path.GetExtension(file))
                    {
                    case ".dll":
                    case ".exe":
                        RegisterFileToScan(monitor, file, scanResult, folderInfo);
                        scanResult.AddAssemblyLocation(file);
                        break;

                    case ".addin":
                        RegisterFileToScan(monitor, file, scanResult, folderInfo);
                        break;

                    case ".addins":
                        ScanAddinsFile(monitor, file, scanResult);
                        break;
                    }
                }
            }
            else if (!scanResult.LocateAssembliesOnly)
            {
                // The folder has been deleted. All add-ins defined in that folder should also be deleted.
                scanResult.RegenerateRelationData = true;
                scanResult.ChangesFound           = true;
                if (scanResult.CheckOnly)
                {
                    return;
                }
                database.DeleteFolderInfo(monitor, folderInfo);
            }

            if (scanResult.LocateAssembliesOnly)
            {
                return;
            }

            // Look for deleted add-ins.

            UpdateDeletedAddins(monitor, folderInfo, scanResult);
        }
Beispiel #29
0
        internal void UninstallAddin(IProgressStatus monitor, string domain, string addinId, string addinFile, AddinScanResult scanResult)
        {
            AddinDescription desc;

            if (!GetAddinDescription (monitor, domain, addinId, addinFile, out desc)) {
                // If we can't get information about the old assembly, just regenerate all relation data
                scanResult.RegenerateRelationData = true;
                return;
            }

            scanResult.AddRemovedAddin (addinId);

            // If the add-in didn't exist, there is nothing left to do

            if (desc == null)
                return;

            // If the add-in already existed, the dependencies of the old add-in need to be re-analyzed

            Util.AddDependencies (desc, scanResult);
            if (desc.IsRoot)
                scanResult.HostIndex.RemoveHostData (desc.AddinId, desc.AddinFile);

            RemoveAddinDescriptionFile (monitor, desc.FileName);
        }
        bool ScanDescription(IProgressStatus monitor, AddinDescription config, Assembly rootAssembly, AddinScanResult scanResult)
        {
            // First of all scan the main module

            ArrayList assemblies           = new ArrayList();
            ArrayList hostExtensionClasses = new ArrayList();

            try {
                foreach (string s in config.MainModule.Assemblies)
                {
                    string   asmFile = Path.Combine(config.BasePath, s);
                    Assembly asm     = Util.LoadAssemblyForReflection(asmFile);
                    assemblies.Add(asm);
                }

                foreach (Assembly asm in assemblies)
                {
                    ScanAssemblyAddinHeaders(config, asm, scanResult);
                }

                // The add-in id and version must be already assigned at this point

                // Clean host data from the index. New data will be added.
                if (scanResult.HostIndex != null)
                {
                    scanResult.HostIndex.RemoveHostData(config.AddinId, config.AddinFile);
                }

                foreach (Assembly asm in assemblies)
                {
                    ScanAssemblyContents(config, asm, hostExtensionClasses, scanResult);
                }

                if (config.IsRoot && scanResult.HostIndex != null)
                {
                    // If the add-in is a root, register its assemblies
                    foreach (Assembly asm in assemblies)
                    {
                        string asmFile = new Uri(asm.CodeBase).LocalPath;
                        scanResult.HostIndex.RegisterAssembly(asmFile, config.AddinId, config.AddinFile);
                    }
                }
            } catch (Exception ex) {
                if (monitor.VerboseLog)
                {
                    monitor.Log("Could not load some add-in assemblies: " + ex.Message);
                }
                scanResult.AddFileToWithFailure(config.AddinFile);
                return(false);
            }

            foreach (Type t in hostExtensionClasses)
            {
                RegisterHostTypeNode(config, t, assemblies);
            }

            // Extension node types may have child nodes declared as attributes. Find them.

            Hashtable internalNodeSets = new Hashtable();

            foreach (ExtensionNodeSet eset in config.ExtensionNodeSets)
            {
                ScanNodeSet(config, eset, assemblies, internalNodeSets);
            }

            foreach (ExtensionPoint ep in config.ExtensionPoints)
            {
                ScanNodeSet(config, ep.NodeSet, assemblies, internalNodeSets);
            }

            // Now scan all modules

            if (!config.IsRoot)
            {
                foreach (ModuleDescription mod in config.OptionalModules)
                {
                    try {
                        assemblies.Clear();
                        foreach (string s in mod.Assemblies)
                        {
                            string   asmFile = Path.Combine(config.BasePath, s);
                            Assembly asm     = Util.LoadAssemblyForReflection(asmFile);
                            assemblies.Add(asm);
                        }
                        foreach (Assembly asm in assemblies)
                        {
                            ScanAssemblyContents(config, asm, null, scanResult);
                        }

                        if (config.IsRoot && scanResult.HostIndex != null)
                        {
                            // If the add-in is a root, register its assemblies
                            foreach (Assembly asm in assemblies)
                            {
                                string asmFile = new Uri(asm.CodeBase).LocalPath;
                                scanResult.HostIndex.RegisterAssembly(asmFile, config.AddinId, config.AddinFile);
                            }
                        }
                    } catch (Exception ex) {
                        if (monitor.VerboseLog)
                        {
                            monitor.Log("Could not load some add-in assemblies: " + ex.Message);
                        }
                        scanResult.AddFileToWithFailure(config.AddinFile);
                    }
                }
            }

            return(true);
        }
Beispiel #31
0
        public void ScanFolder(IProgressStatus monitor, string path, string domain, AddinScanResult scanResult)
        {
            path = Path.GetFullPath (path);

            // Avoid folders including each other
            if (!scanResult.VisitFolder (path))
                return;

            AddinScanFolderInfo folderInfo;
            if (!database.GetFolderInfoForPath (monitor, path, out folderInfo)) {
                // folderInfo file was corrupt.
                // Just in case, we are going to regenerate all relation data.
                if (!fs.DirectoryExists (path))
                    scanResult.RegenerateRelationData = true;
            } else {
                // Directory is included but it doesn't exist. Ignore it.
                if (folderInfo == null && !fs.DirectoryExists (path))
                    return;
            }

            // if domain is null it means that a new domain has to be created.

            bool sharedFolder = domain == AddinDatabase.GlobalDomain;
            bool isNewFolder = folderInfo == null;

            if (isNewFolder) {
                // No folder info. It is the first time this folder is scanned.
                // There is no need to store this object if the folder does not
                // contain add-ins.
                folderInfo = new AddinScanFolderInfo (path);
            }

            if (!sharedFolder && (folderInfo.SharedFolder || folderInfo.Domain != domain)) {
                // If the folder already has a domain, reuse it
                if (domain == null && folderInfo.RootsDomain != null && folderInfo.RootsDomain != AddinDatabase.GlobalDomain)
                    domain = folderInfo.RootsDomain;
                else if (domain == null) {
                    folderInfo.Domain = domain = database.GetUniqueDomainId ();
                    scanResult.RegenerateRelationData = true;
                }
                else {
                    folderInfo.Domain = domain;
                    if (!isNewFolder) {
                        // Domain has changed. Update the folder info and regenerate everything.
                        scanResult.RegenerateRelationData = true;
                        scanResult.RegisterModifiedFolderInfo (folderInfo);
                    }
                }
            }
            else if (!folderInfo.SharedFolder && sharedFolder) {
                scanResult.RegenerateRelationData = true;
            }

            folderInfo.SharedFolder = sharedFolder;

            // If there is no domain assigned to the host, get one now
            if (scanResult.Domain == AddinDatabase.UnknownDomain)
                scanResult.Domain = domain;

            // Discard folders not belonging to the required domain
            if (scanResult.Domain != null && domain != scanResult.Domain && domain != AddinDatabase.GlobalDomain) {
                return;
            }

            if (monitor.LogLevel > 1 && !scanResult.LocateAssembliesOnly)
                monitor.Log ("Checking: " + path);

            if (fs.DirectoryExists (path))
            {
                IEnumerable<string> files = fs.GetFiles (path);

                // First of all, look for .addin files. Addin files must be processed before
                // assemblies, because they may add files to the ignore list (i.e., assemblies
                // included in .addin files won't be scanned twice).
                foreach (string file in files) {
                    if (file.EndsWith (".addin.xml") || file.EndsWith (".addin")) {
                        RegisterFileToScan (monitor, file, scanResult, folderInfo);
                    }
                }

                // Now scan assemblies. They can also add files to the ignore list.

                foreach (string file in files) {
                    string ext = Path.GetExtension (file).ToLower ();
                    if (ext == ".dll" || ext == ".exe") {
                        RegisterFileToScan (monitor, file, scanResult, folderInfo);
                        scanResult.AddAssemblyLocation (file);
                    }
                }

                // Finally scan .addins files

                foreach (string file in files) {
                    if (Path.GetExtension (file).EndsWith (".addins")) {
                        ScanAddinsFile (monitor, file, domain, scanResult);
                    }
                }
            }
            else if (!scanResult.LocateAssembliesOnly) {
                // The folder has been deleted. All add-ins defined in that folder should also be deleted.
                scanResult.RegenerateRelationData = true;
                scanResult.ChangesFound = true;
                if (scanResult.CheckOnly)
                    return;
                database.DeleteFolderInfo (monitor, folderInfo);
            }

            if (scanResult.LocateAssembliesOnly)
                return;

            // Look for deleted add-ins.

            UpdateDeletedAddins (monitor, folderInfo, scanResult);
        }
Beispiel #32
0
        void ScanAssemblyContents(IAssemblyReflector reflector, AddinDescription config, ModuleDescription module, object asm, AddinScanResult scanResult)
        {
            bool isMainModule = module == config.MainModule;

            // Get dependencies

            object[] deps = reflector.GetCustomAttributes (asm, typeof(AddinDependencyAttribute), false);
            foreach (AddinDependencyAttribute dep in deps) {
                AddinDependency adep = new AddinDependency ();
                adep.AddinId = dep.Id;
                adep.Version = dep.Version;
                module.Dependencies.Add (adep);
            }

            if (isMainModule) {

                // Get properties

                object[] props = reflector.GetCustomAttributes (asm, typeof(AddinPropertyAttribute), false);
                foreach (AddinPropertyAttribute prop in props)
                    config.Properties.SetPropertyValue (prop.Name, prop.Value, prop.Locale);

                // Get extension points

                object[] extPoints = reflector.GetCustomAttributes (asm, typeof(ExtensionPointAttribute), false);
                foreach (ExtensionPointAttribute ext in extPoints) {
                    ExtensionPoint ep = config.AddExtensionPoint (ext.Path);
                    ep.Description = ext.Description;
                    ep.Name = ext.Name;
                    ExtensionNodeType nt = ep.AddExtensionNode (ext.NodeName, ext.NodeTypeName);
                    nt.ExtensionAttributeTypeName = ext.ExtensionAttributeTypeName;
                }
            }

            // Look for extension nodes declared using assembly attributes

            foreach (CustomAttribute att in reflector.GetRawCustomAttributes (asm, typeof(CustomExtensionAttribute), true))
                AddCustomAttributeExtension (module, att, "Type");

            // Get extensions or extension points applied to types

            foreach (object t in reflector.GetAssemblyTypes (asm)) {

                string typeFullName = reflector.GetTypeFullName (t);

                // Look for extensions

                object[] extensionAtts = reflector.GetCustomAttributes (t, typeof(ExtensionAttribute), false);
                if (extensionAtts.Length > 0) {
                    Dictionary<string,ExtensionNodeDescription> nodes = new Dictionary<string, ExtensionNodeDescription> ();
                    ExtensionNodeDescription uniqueNode = null;
                    foreach (ExtensionAttribute eatt in extensionAtts) {
                        string path;
                        string nodeName = eatt.NodeName;

                        if (eatt.TypeName.Length > 0) {
                            path = "$" + eatt.TypeName;
                        }
                        else if (eatt.Path.Length == 0) {
                            path = GetBaseTypeNameList (reflector, t);
                            if (path == "$") {
                                // The type does not implement any interface and has no superclass.
                                // Will be reported later as an error.
                                path = "$" + typeFullName;
                            }
                        } else {
                            path = eatt.Path;
                        }

                        ExtensionNodeDescription elem = module.AddExtensionNode (path, nodeName);
                        nodes [path] = elem;
                        uniqueNode = elem;

                        if (eatt.Id.Length > 0) {
                            elem.SetAttribute ("id", eatt.Id);
                            elem.SetAttribute ("type", typeFullName);
                        } else {
                            elem.SetAttribute ("id", typeFullName);
                        }
                        if (eatt.InsertAfter.Length > 0)
                            elem.SetAttribute ("insertafter", eatt.InsertAfter);
                        if (eatt.InsertBefore.Length > 0)
                            elem.SetAttribute ("insertbefore", eatt.InsertBefore);
                    }

                    // Get the node attributes

                    foreach (ExtensionAttributeAttribute eat in reflector.GetCustomAttributes (t, typeof(ExtensionAttributeAttribute), false)) {
                        ExtensionNodeDescription node;
                        if (!string.IsNullOrEmpty (eat.Path))
                            nodes.TryGetValue (eat.Path, out node);
                        else if (eat.TypeName.Length > 0)
                            nodes.TryGetValue ("$" + eat.TypeName, out node);
                        else {
                            if (nodes.Count > 1)
                                throw new Exception ("Missing type or extension path value in ExtensionAttribute for type '" + typeFullName + "'.");
                            node = uniqueNode;
                        }
                        if (node == null)
                            throw new Exception ("Invalid type or path value in ExtensionAttribute for type '" + typeFullName + "'.");

                        node.SetAttribute (eat.Name ?? string.Empty, eat.Value ?? string.Empty);
                    }
                }
                else {
                    // Look for extension points

                    extensionAtts = reflector.GetCustomAttributes (t, typeof(TypeExtensionPointAttribute), false);
                    if (extensionAtts.Length > 0 && isMainModule) {
                        foreach (TypeExtensionPointAttribute epa in extensionAtts) {
                            ExtensionPoint ep;

                            ExtensionNodeType nt = new ExtensionNodeType ();

                            if (epa.Path.Length > 0) {
                                ep = config.AddExtensionPoint (epa.Path);
                            }
                            else {
                                ep = config.AddExtensionPoint (GetDefaultTypeExtensionPath (config, typeFullName));
                                nt.ObjectTypeName = typeFullName;
                            }
                            nt.Id = epa.NodeName;
                            nt.TypeName = epa.NodeTypeName;
                            nt.ExtensionAttributeTypeName = epa.ExtensionAttributeTypeName;
                            ep.NodeSet.NodeTypes.Add (nt);
                            ep.Description = epa.Description;
                            ep.Name = epa.Name;
                            ep.RootAddin = config.AddinId;
                            ep.SetExtensionsAddinId (config.AddinId);
                        }
                    }
                    else {
                        // Look for custom extension attribtues
                        foreach (CustomAttribute att in reflector.GetRawCustomAttributes (t, typeof(CustomExtensionAttribute), false)) {
                            ExtensionNodeDescription elem = AddCustomAttributeExtension (module, att, "Type");
                            elem.SetAttribute ("type", typeFullName);
                            if (string.IsNullOrEmpty (elem.GetAttribute ("id")))
                                elem.SetAttribute ("id", typeFullName);
                        }
                    }
                }
            }
        }
Beispiel #33
0
        public AddinDescription ScanSingleFile(IProgressStatus monitor, string file, AddinScanResult scanResult)
        {
            AddinDescription config = null;

            if (monitor.LogLevel > 1)
                monitor.Log ("Scanning file: " + file);

            monitor.Log ("plog:scan:" + file);

            try {
                string ext = Path.GetExtension (file).ToLower ();
                bool scanSuccessful;

                if (ext == ".dll" || ext == ".exe")
                    scanSuccessful = ScanAssembly (monitor, file, scanResult, out config);
                else
                    scanSuccessful = ScanConfigAssemblies (monitor, file, scanResult, out config);

                if (scanSuccessful && config != null) {

                    config.Domain = "global";
                    if (config.Version.Length == 0)
                        config.Version = "0.0.0.0";

                    if (config.LocalId.Length == 0) {
                        // Generate an internal id for this add-in
                        config.LocalId = database.GetUniqueAddinId (file, "", config.Namespace, config.Version);
                    }
                }
            }
            catch (Exception ex) {
                monitor.ReportError ("Unexpected error while scanning file: " + file, ex);
            } finally {
                monitor.Log ("plog:endscan");
            }
            return config;
        }
Beispiel #34
0
        bool ScanDescription(IProgressStatus monitor, IAssemblyReflector reflector, AddinDescription config, object rootAssembly, AddinScanResult scanResult)
        {
            // First of all scan the main module

            ArrayList assemblies = new ArrayList ();

            try {
                string rootAsmFile = null;

                if (rootAssembly != null) {
                    ScanAssemblyAddinHeaders (reflector, config, rootAssembly, scanResult);
                    ScanAssemblyImports (reflector, config.MainModule, rootAssembly);
                    assemblies.Add (rootAssembly);
                    rootAsmFile = Path.GetFileName (config.AddinFile);
                }

                // The assembly list may be modified while scanning the headears, so
                // we use a for loop instead of a foreach
                for (int n=0; n<config.MainModule.Assemblies.Count; n++) {
                    string s = config.MainModule.Assemblies [n];
                    string asmFile = Path.GetFullPath (Path.Combine (config.BasePath, s));
                    scanResult.AddPathToIgnore (asmFile);
                    if (s == rootAsmFile || config.MainModule.IgnorePaths.Contains (s))
                        continue;
                    object asm = reflector.LoadAssembly (asmFile);
                    assemblies.Add (asm);
                    ScanAssemblyAddinHeaders (reflector, config, asm, scanResult);
                    ScanAssemblyImports (reflector, config.MainModule, asm);
                }

                // Add all data files to the ignore file list. It avoids scanning assemblies
                // which are included as 'data' in an add-in.
                foreach (string df in config.MainModule.DataFiles) {
                    string file = Path.Combine (config.BasePath, df);
                    scanResult.AddPathToIgnore (Path.GetFullPath (file));
                }
                foreach (string df in config.MainModule.IgnorePaths) {
                    string path = Path.Combine (config.BasePath, df);
                    scanResult.AddPathToIgnore (Path.GetFullPath (path));
                }

                // The add-in id and version must be already assigned at this point

                // Clean host data from the index. New data will be added.
                if (scanResult.HostIndex != null)
                    scanResult.HostIndex.RemoveHostData (config.AddinId, config.AddinFile);

                foreach (object asm in assemblies)
                    ScanAssemblyContents (reflector, config, config.MainModule, asm, scanResult);

            } catch (Exception ex) {
                ReportReflectionException (monitor, ex, config, scanResult);
                return false;
            }

            // Extension node types may have child nodes declared as attributes. Find them.

            Hashtable internalNodeSets = new Hashtable ();

            ArrayList setsCopy = new ArrayList ();
            setsCopy.AddRange (config.ExtensionNodeSets);
            foreach (ExtensionNodeSet eset in setsCopy)
                ScanNodeSet (reflector, config, eset, assemblies, internalNodeSets);

            foreach (ExtensionPoint ep in config.ExtensionPoints) {
                ScanNodeSet (reflector, config, ep.NodeSet, assemblies, internalNodeSets);
            }

            // Now scan all modules

            if (!config.IsRoot) {
                foreach (ModuleDescription mod in config.OptionalModules) {
                    try {
                        assemblies.Clear ();
                        for (int n=0; n<mod.Assemblies.Count; n++) {
                            string s = mod.Assemblies [n];
                            if (mod.IgnorePaths.Contains (s))
                                continue;
                            string asmFile = Path.Combine (config.BasePath, s);
                            object asm = reflector.LoadAssembly (asmFile);
                            assemblies.Add (asm);
                            scanResult.AddPathToIgnore (Path.GetFullPath (asmFile));
                            ScanAssemblyImports (reflector, mod, asm);
                        }
                        // Add all data files to the ignore file list. It avoids scanning assemblies
                        // which are included as 'data' in an add-in.
                        foreach (string df in mod.DataFiles) {
                            string file = Path.Combine (config.BasePath, df);
                            scanResult.AddPathToIgnore (Path.GetFullPath (file));
                        }
                        foreach (string df in mod.IgnorePaths) {
                            string path = Path.Combine (config.BasePath, df);
                            scanResult.AddPathToIgnore (Path.GetFullPath (path));
                        }

                        foreach (object asm in assemblies)
                            ScanAssemblyContents (reflector, config, mod, asm, scanResult);

                    } catch (Exception ex) {
                        ReportReflectionException (monitor, ex, config, scanResult);
                    }
                }
            }

            config.StoreFileInfo ();
            return true;
        }
Beispiel #35
0
 IAssemblyReflector GetReflector(IProgressStatus monitor, AddinScanResult scanResult, string filePath)
 {
     IAssemblyReflector reflector = fs.GetReflectorForFile (scanResult, filePath);
     object coreAssembly;
     if (!coreAssemblies.TryGetValue (reflector, out coreAssembly)) {
         if (monitor.LogLevel > 1)
             monitor.Log ("Using assembly reflector: " + reflector.GetType ());
         coreAssemblies [reflector] = coreAssembly = reflector.LoadAssembly (GetType().Assembly.Location);
     }
     return reflector;
 }
		internal void UninstallRootAddin (IProgressStatus monitor, string addinId, string addinFile, AddinScanResult scanResult)
		{
			string file = fileDatabase.GetSharedObjectFile (AddinCachePath, addinId, ".mroot", addinFile);
			DeleteAddin (monitor, file, scanResult);
		}
Beispiel #37
0
 public AddinScanner(AddinDatabase database, AddinScanResult scanResult, IProgressStatus monitor)
 {
     this.database = database;
     fs = database.FileSystem;
 }
		public Assembly Resolve (object s, ResolveEventArgs args)
		{
			if (scanResult == null) {
				scanResult = new AddinScanResult ();
				scanResult.LocateAssembliesOnly = true;
			
				foreach (string dir in registry.AddinDirectories)
					scanner.ScanFolder (progressStatus, dir, scanResult);
			}
		
			string afile = scanResult.GetAssemblyLocation (args.Name);
			if (afile != null)
				return Util.LoadAssemblyForReflection (afile);
			else
				return null;
		}
Beispiel #39
0
        bool ScanAssembly(IProgressStatus monitor, string filePath, AddinScanResult scanResult, out AddinDescription config)
        {
            config = null;

            try {
                IAssemblyReflector reflector = GetReflector (monitor, scanResult, filePath);
                object asm = reflector.LoadAssembly (filePath);
                if (asm == null)
                    throw new Exception ("Could not load assembly: " + filePath);

                // Get the config file from the resources, if there is one

                foreach (string res in reflector.GetResourceNames (asm)) {
                    if (res.EndsWith (".addin") || res.EndsWith (".addin.xml")) {
                        using (Stream s = reflector.GetResourceStream (asm, res)) {
                            AddinDescription ad = AddinDescription.Read (s, Path.GetDirectoryName (filePath));
                            if (config != null) {
                                if (!config.IsExtensionModel && !ad.IsExtensionModel) {
                                    // There is more than one add-in definition
                                    monitor.ReportError ("Duplicate add-in definition found in assembly: " + filePath, null);
                                    return false;
                                }
                                config = AddinDescription.Merge (config, ad);
                            } else
                                config = ad;
                        }
                    }
                }

                if (config == null) {
                    // In this case, only scan the assembly if it has the Addin attribute.
                    AddinAttribute att = (AddinAttribute) reflector.GetCustomAttribute (asm, typeof(AddinAttribute), false);
                    if (att == null)
                        return true;

                    config = new AddinDescription ();
                }

                config.SetBasePath (Path.GetDirectoryName (filePath));
                config.AddinFile = filePath;

                string rasmFile = Path.GetFileName (filePath);
                if (!config.MainModule.Assemblies.Contains (rasmFile))
                    config.MainModule.Assemblies.Add (rasmFile);

                return ScanDescription (monitor, reflector, config, asm, scanResult);
            }
            catch (Exception ex) {
                // Something went wrong while scanning the assembly. We'll ignore it for now.
                monitor.ReportError ("There was an error while scanning assembly: " + filePath, ex);
                return false;
            }
        }
		internal void ScanFolders (IProgressStatus monitor, AddinScanResult scanResult)
		{
			IDisposable checkLock = null;
			
			if (scanResult.CheckOnly)
				checkLock = fileDatabase.LockRead ();
			else {
				// All changes are done in a transaction, which won't be committed until
				// all files have been updated.
				
				if (!fileDatabase.BeginTransaction ()) {
					// The database is already being updated. Can't do anything for now.
					return;
				}
			}
			
			EventInfo einfo = typeof(AppDomain).GetEvent ("ReflectionOnlyAssemblyResolve");
			ResolveEventHandler resolver = new ResolveEventHandler (OnResolveAddinAssembly);
			
			try
			{
				// Perform the add-in scan
				
				if (!scanResult.CheckOnly) {
					AppDomain.CurrentDomain.AssemblyResolve += resolver;
					if (einfo != null) einfo.AddEventHandler (AppDomain.CurrentDomain, resolver);
				}
				
				InternalScanFolders (monitor, scanResult);
				
				if (!scanResult.CheckOnly)
					fileDatabase.CommitTransaction ();
			}
			catch {
				if (!scanResult.CheckOnly)
					fileDatabase.RollbackTransaction ();
				throw;
			}
			finally {
				currentScanResult = null;
				
				if (scanResult.CheckOnly)
					checkLock.Dispose ();
				else {
					AppDomain.CurrentDomain.AssemblyResolve -= resolver;
					if (einfo != null) einfo.RemoveEventHandler (AppDomain.CurrentDomain, resolver);
				}
			}
		}
Beispiel #41
0
        public void ScanAddinsFile(IProgressStatus monitor, string file, string domain, AddinScanResult scanResult)
        {
            XmlTextReader r = null;
            ArrayList directories = new ArrayList ();
            ArrayList directoriesWithSubdirs = new ArrayList ();
            string basePath = Path.GetDirectoryName (file);

            try {
                r = new XmlTextReader (fs.OpenTextFile (file));
                r.MoveToContent ();
                if (r.IsEmptyElement)
                    return;
                r.ReadStartElement ();
                r.MoveToContent ();
                while (r.NodeType != XmlNodeType.EndElement) {
                    if (r.NodeType == XmlNodeType.Element && r.LocalName == "Directory") {
                        string subs = r.GetAttribute ("include-subdirs");
                        string sdom;
                        string share = r.GetAttribute ("shared");
                        if (share == "true")
                            sdom = AddinDatabase.GlobalDomain;
                        else if (share == "false")
                            sdom = null;
                        else
                            sdom = domain; // Inherit the domain

                        string path = r.ReadElementString ().Trim ();
                        if (path.Length > 0) {
                            path = Util.NormalizePath (path);
                            if (subs == "true")
                                directoriesWithSubdirs.Add (new string[] {path, sdom});
                            else
                                directories.Add (new string[] {path, sdom});
                        }
                    }
                    else if (r.NodeType == XmlNodeType.Element && r.LocalName == "GacAssembly") {
                        string aname = r.ReadElementString ().Trim ();
                        if (aname.Length > 0) {
                            aname = Util.NormalizePath (aname);
                            aname = Util.GetGacPath (aname);
                            if (aname != null) {
                                // Gac assemblies always use the global domain
                                directories.Add (new string[] {aname, AddinDatabase.GlobalDomain});
                            }
                        }
                    }
                    else if (r.NodeType == XmlNodeType.Element && r.LocalName == "Exclude") {
                        string path = r.ReadElementString ().Trim ();
                        if (path.Length > 0) {
                            path = Util.NormalizePath (path);
                            if (!Path.IsPathRooted (path))
                                path = Path.Combine (basePath, path);
                            scanResult.AddPathToIgnore (Path.GetFullPath (path));
                        }
                    }
                    else
                        r.Skip ();
                    r.MoveToContent ();
                }
            } catch (Exception ex) {
                monitor.ReportError ("Could not process addins file: " + file, ex);
                return;
            } finally {
                if (r != null)
                    r.Close ();
            }

            foreach (string[] d in directories) {
                string dir = d[0];
                if (!Path.IsPathRooted (dir))
                    dir = Path.Combine (basePath, dir);
                ScanFolder (monitor, dir, d[1], scanResult);
            }
            foreach (string[] d in directoriesWithSubdirs) {
                string dir = d[0];
                if (!Path.IsPathRooted (dir))
                    dir = Path.Combine (basePath, dir);
                ScanFolderRec (monitor, dir, d[1], scanResult);
            }
        }
        public void ScanFolder(IProgressStatus monitor, string path, string domain, AddinScanResult scanResult)
        {
            path = Util.GetFullPath(path);

            // Avoid folders including each other
            if (!scanResult.VisitFolder(path))
            {
                return;
            }

            AddinScanFolderInfo folderInfo;

            if (!database.GetFolderInfoForPath(monitor, path, out folderInfo))
            {
                // folderInfo file was corrupt.
                // Just in case, we are going to regenerate all relation data.
                if (!Directory.Exists(path))
                {
                    scanResult.RegenerateRelationData = true;
                }
            }
            else
            {
                // Directory is included but it doesn't exist. Ignore it.
                if (folderInfo == null && !Directory.Exists(path))
                {
                    return;
                }
            }

            // if domain is null it means that a new domain has to be created.

            bool sharedFolder = domain == AddinDatabase.GlobalDomain;
            bool isNewFolder  = folderInfo == null;

            if (isNewFolder)
            {
                // No folder info. It is the first time this folder is scanned.
                // There is no need to store this object if the folder does not
                // contain add-ins.
                folderInfo = new AddinScanFolderInfo(path);
            }

            if (!sharedFolder && (folderInfo.SharedFolder || folderInfo.Domain != domain))
            {
                // If the folder already has a domain, reuse it
                if (domain == null && folderInfo.RootsDomain != null && folderInfo.RootsDomain != AddinDatabase.GlobalDomain)
                {
                    domain = folderInfo.RootsDomain;
                }
                else if (domain == null)
                {
                    folderInfo.Domain = domain = database.GetUniqueDomainId();
                    scanResult.RegenerateRelationData = true;
                }
                else
                {
                    folderInfo.Domain = domain;
                    if (!isNewFolder)
                    {
                        // Domain has changed. Update the folder info and regenerate everything.
                        scanResult.RegenerateRelationData = true;
                        scanResult.RegisterModifiedFolderInfo(folderInfo);
                    }
                }
            }
            else if (!folderInfo.SharedFolder && sharedFolder)
            {
                scanResult.RegenerateRelationData = true;
            }

            folderInfo.SharedFolder = sharedFolder;

            // If there is no domain assigned to the host, get one now
            if (scanResult.Domain == AddinDatabase.UnknownDomain)
            {
                scanResult.Domain = domain;
            }

            // Discard folders not belonging to the required domain
            if (scanResult.Domain != null && domain != scanResult.Domain && domain != AddinDatabase.GlobalDomain)
            {
                return;
            }

            if (monitor.LogLevel > 1 && !scanResult.LocateAssembliesOnly)
            {
                monitor.Log("Checking: " + path);
            }

            if (Directory.Exists(path))
            {
                string[] files = Directory.GetFiles(path);

                // First of all, look for .addin files. Addin files must be processed before
                // assemblies, because they may add files to the ignore list (i.e., assemblies
                // included in .addin files won't be scanned twice).
                foreach (string file in files)
                {
                    if (file.EndsWith(".addin.xml") || file.EndsWith(".addin"))
                    {
                        RegisterFileToScan(monitor, file, scanResult, folderInfo);
                    }
                }

                // Now scan assemblies. They can also add files to the ignore list.

                foreach (string file in files)
                {
                    string ext = Path.GetExtension(file).ToLower();
                    if (ext == ".dll" || ext == ".exe")
                    {
                        RegisterFileToScan(monitor, file, scanResult, folderInfo);
                        scanResult.AddAssemblyLocation(file);
                    }
                }

                // Finally scan .addins files

                foreach (string file in files)
                {
                    if (Path.GetExtension(file).EndsWith(".addins"))
                    {
                        ScanAddinsFile(monitor, file, domain, scanResult);
                    }
                }
            }
            else if (!scanResult.LocateAssembliesOnly)
            {
                // The folder has been deleted. All add-ins defined in that folder should also be deleted.
                scanResult.RegenerateRelationData = true;
                scanResult.ChangesFound           = true;
                if (scanResult.CheckOnly)
                {
                    return;
                }
                database.DeleteFolderInfo(monitor, folderInfo);
            }

            if (scanResult.LocateAssembliesOnly)
            {
                return;
            }

            // Look for deleted add-ins.

            UpdateDeletedAddins(monitor, folderInfo, scanResult);
        }
Beispiel #43
0
        bool ScanConfigAssemblies(IProgressStatus monitor, string filePath, AddinScanResult scanResult, out AddinDescription config)
        {
            config = null;

            try {
                IAssemblyReflector reflector = GetReflector (monitor, scanResult, filePath);

                string basePath = Path.GetDirectoryName (filePath);

                using (var s = fs.OpenFile (filePath)) {
                    config = AddinDescription.Read (s, basePath);
                }
                config.FileName = filePath;
                config.SetBasePath (basePath);
                config.AddinFile = filePath;

                return ScanDescription (monitor, reflector, config, null, scanResult);
            }
            catch (Exception ex) {
                // Something went wrong while scanning the assembly. We'll ignore it for now.
                monitor.ReportError ("There was an error while scanning add-in: " + filePath, ex);
                return false;
            }
        }
        void ScanAssemblyContents(AddinDescription config, Assembly asm, ArrayList hostExtensionClasses, AddinScanResult scanResult)
        {
            // Get dependencies

            object[] deps = asm.GetCustomAttributes(typeof(AddinDependencyAttribute), false);
            foreach (AddinDependencyAttribute dep in deps)
            {
                AddinDependency adep = new AddinDependency();
                adep.AddinId = dep.Id;
                adep.Version = dep.Version;
                config.MainModule.Dependencies.Add(adep);
            }

            // Get extension points

            object[] extPoints = asm.GetCustomAttributes(typeof(ExtensionPointAttribute), false);
            foreach (ExtensionPointAttribute ext in extPoints)
            {
                ExtensionPoint ep = config.AddExtensionPoint(ext.Path);
                ep.Description = ext.Description;
                ep.Name        = ext.Name;
                ep.AddExtensionNode(ext.NodeName, ext.NodeType.FullName);
            }

            foreach (Type t in asm.GetTypes())
            {
                if (Attribute.IsDefined(t, typeof(ExtensionAttribute)))
                {
                    foreach (ExtensionAttribute eatt in t.GetCustomAttributes(typeof(ExtensionAttribute), false))
                    {
                        string path;
                        string nodeName;

                        if (eatt.Path.Length == 0)
                        {
                            if (config.IsRoot)
                            {
                                // The extension point must be one of the defined by the assembly
                                // Look for it later, when the assembly has been fully scanned.
                                hostExtensionClasses.Add(t);
                                continue;
                            }
                            else
                            {
                                path = GetBaseTypeNameList(t);
                                if (path == "$")
                                {
                                    // The type does not implement any interface and has no superclass.
                                    // Will be reported later as an error.
                                    path = "$" + t.FullName;
                                }
                                nodeName = "Type";
                            }
                        }
                        else
                        {
                            path     = eatt.Path;
                            nodeName = eatt.NodeName;
                        }

                        ExtensionNodeDescription elem = config.MainModule.AddExtensionNode(path, nodeName);
                        if (eatt.Id.Length > 0)
                        {
                            elem.SetAttribute("id", eatt.Id);
                            elem.SetAttribute("type", t.FullName);
                        }
                        else
                        {
                            elem.SetAttribute("id", t.FullName);
                        }
                        if (eatt.InsertAfter.Length > 0)
                        {
                            elem.SetAttribute("insertafter", eatt.InsertAfter);
                        }
                        if (eatt.InsertBefore.Length > 0)
                        {
                            elem.SetAttribute("insertbefore", eatt.InsertAfter);
                        }
                    }
                }
                else if (Attribute.IsDefined(t, typeof(TypeExtensionPointAttribute)))
                {
                    foreach (TypeExtensionPointAttribute epa in t.GetCustomAttributes(typeof(TypeExtensionPointAttribute), false))
                    {
                        ExtensionPoint ep;

                        ExtensionNodeType nt = new ExtensionNodeType();

                        if (epa.Path.Length > 0)
                        {
                            ep = config.AddExtensionPoint(epa.Path);
                        }
                        else
                        {
                            ep = config.AddExtensionPoint(GetDefaultTypeExtensionPath(config, t));
                            nt.ObjectTypeName = t.FullName;
                        }
                        nt.Id       = epa.NodeName;
                        nt.TypeName = epa.NodeType.FullName;
                        ep.NodeSet.NodeTypes.Add(nt);
                        ep.Description = epa.Description;
                        ep.Name        = epa.Name;
                        ep.RootAddin   = config.AddinId;
                        ep.SetExtensionsAddinId(config.AddinId);
                    }
                }
            }
        }
		internal void UninstallAddin (IProgressStatus monitor, string addinId, AddinScanResult scanResult)
		{
			scanResult.AddRemovedAddin (addinId);
			string file = GetDescriptionPath (addinId);
			DeleteAddin (monitor, file, scanResult);
		}
Beispiel #46
0
		bool ScanAssembly (IProgressStatus monitor, string filePath, AddinScanResult scanResult, out AddinDescription config)
		{
			config = null;
				
			try {
				IAssemblyReflector reflector = GetReflector (monitor, scanResult, filePath);
				object asm = reflector.LoadAssembly (filePath);
				if (asm == null)
					throw new Exception ("Could not load assembly: " + filePath);
				
				// Get the config file from the resources, if there is one
				
				if (!ScanEmbeddedDescription (monitor, filePath, reflector, asm, out config))
					return false;
				
				if (config == null || config.IsExtensionModel) {
					// In this case, only scan the assembly if it has the Addin attribute.
					AddinAttribute att = (AddinAttribute) reflector.GetCustomAttribute (asm, typeof(AddinAttribute), false);
					if (att == null) {
						config = null;
						return true;
					}

					if (config == null)
						config = new AddinDescription ();
				}
				
				config.SetBasePath (Path.GetDirectoryName (filePath));
				config.AddinFile = filePath;
				
				string rasmFile = Path.GetFileName (filePath);
				if (!config.MainModule.Assemblies.Contains (rasmFile))
					config.MainModule.Assemblies.Add (rasmFile);
				
				return ScanDescription (monitor, reflector, config, asm, scanResult);
			}
			catch (Exception ex) {
				// Something went wrong while scanning the assembly. We'll ignore it for now.
				monitor.ReportError ("There was an error while scanning assembly: " + filePath, ex);
				return false;
			}
		}
		void DeleteAddin (IProgressStatus monitor, string file, AddinScanResult scanResult)
		{
			if (!fileDatabase.Exists (file))
				return;
			
			// Add-in already existed. The dependencies of the old add-in need to be re-analized
						
			AddinDescription desc;
			if (ReadAddinDescription (monitor, file, out desc)) {
				Util.AddDependencies (desc, scanResult);
				if (desc.IsRoot)
					scanResult.HostIndex.RemoveHostData (desc.AddinId, desc.AddinFile);
			} else
				// If we can't get information about the old assembly, just regenerate all relation data
				scanResult.RegenerateRelationData = true;

			SafeDelete (monitor, file);
		}
Beispiel #48
0
		bool ScanSubmodule (IProgressStatus monitor, ModuleDescription mod, IAssemblyReflector reflector, AddinDescription config, AddinScanResult scanResult, string assemblyName, object asm)
		{
			AddinDescription mconfig;
			ScanEmbeddedDescription (monitor, assemblyName, reflector, asm, out mconfig);
			if (mconfig != null) {
				if (!mconfig.IsExtensionModel) {
					monitor.ReportError ("Submodules can't define new add-ins: " + assemblyName, null);
					return false;
				}
				if (mconfig.OptionalModules.Count != 0) {
					monitor.ReportError ("Submodules can't define nested submodules: " + assemblyName, null);
					return false;
				}
				if (mconfig.ConditionTypes.Count != 0) {
					monitor.ReportError ("Submodules can't define condition types: " + assemblyName, null);
					return false;
				}
				if (mconfig.ExtensionNodeSets.Count != 0) {
					monitor.ReportError ("Submodules can't define extension node sets: " + assemblyName, null);
					return false;
				}
				if (mconfig.ExtensionPoints.Count != 0) {
					monitor.ReportError ("Submodules can't define extension points sets: " + assemblyName, null);
					return false;
				}
				mod.MergeWith (mconfig.MainModule);
			}
			ScanAssemblyContents (reflector, config, mod, asm, scanResult);
			return true;
		}
		internal bool CheckFolders (IProgressStatus monitor)
		{
			using (fileDatabase.LockRead ()) {
				AddinScanResult scanResult = new AddinScanResult ();
				scanResult.CheckOnly = true;
				InternalScanFolders (monitor, scanResult);
				return scanResult.ChangesFound;
			}
		}
Beispiel #50
0
 void InternalScanFolders(IProgressStatus monitor, AddinScanResult scanResult)
 {
     try {
         fs.ScanStarted ();
         InternalScanFolders2 (monitor, scanResult);
     } finally {
         fs.ScanFinished ();
     }
 }
		void InternalScanFolders (IProgressStatus monitor, AddinScanResult scanResult)
		{
			DateTime tim = DateTime.Now;
			
			DatabaseInfrastructureCheck (monitor);
			if (monitor.IsCanceled)
				return;
			
			try {
				scanResult.HostIndex = GetAddinHostIndex ();
			}
			catch (Exception ex) {
				if (scanResult.CheckOnly) {
					scanResult.ChangesFound = true;
					return;
				}
				monitor.ReportError ("Add-in root index is corrupt. The add-in database will be regenerated.", ex);
				scanResult.RegenerateAllData = true;
			}
			
			AddinScanner scanner = new AddinScanner (this);
			
			// Check if any of the previously scanned folders has been deleted
			
			foreach (string file in Directory.GetFiles (AddinFolderCachePath, "*.data")) {
				AddinScanFolderInfo folderInfo;
				bool res = ReadFolderInfo (monitor, file, out folderInfo);
				if (!res || !Directory.Exists (folderInfo.Folder)) {
					if (res) {
						// Folder has been deleted. Remove the add-ins it had.
						scanner.UpdateDeletedAddins (monitor, folderInfo, scanResult);
					}
					else {
						// Folder info file corrupt. Regenerate all.
						scanResult.ChangesFound = true;
						scanResult.RegenerateRelationData = true;
					}
					
					if (!scanResult.CheckOnly)
						SafeDelete (monitor, file);
					else
						return;
				}
			}
			
			// Look for changes in the add-in folders
			
			foreach (string dir in registry.AddinDirectories) {
				if (dir == registry.DefaultAddinsFolder)
					scanner.ScanFolderRec (monitor, dir, scanResult);
				else
					scanner.ScanFolder (monitor, dir, scanResult);
				if (scanResult.CheckOnly) {
					if (scanResult.ChangesFound || monitor.IsCanceled)
						return;
				}
			}
			
			if (scanResult.CheckOnly)
				return;
			
			// Scan the files which have been modified
			
			currentScanResult = scanResult;

			foreach (FileToScan file in scanResult.FilesToScan)
				scanner.ScanFile (monitor, file.File, file.AddinScanFolderInfo, scanResult);

			// Save folder info
			
			foreach (AddinScanFolderInfo finfo in scanResult.ModifiedFolderInfos)
				SaveFolderInfo (monitor, finfo);

			if (monitor.VerboseLog)
				monitor.Log ("Folders scan completed (" + (int) (DateTime.Now - tim).TotalMilliseconds + " ms)");

			SaveAddinHostIndex ();
			ResetCachedData ();
			
			if (!scanResult.ChangesFound) {
				if (monitor.VerboseLog)
					monitor.Log ("No changes found");
				return;
			}
			
			tim = DateTime.Now;
			try {
				if (scanResult.RegenerateRelationData)
					scanResult.AddinsToUpdateRelations = null;
				
				GenerateAddinExtensionMapsInternal (monitor, scanResult.AddinsToUpdateRelations, scanResult.RemovedAddins);
			}
			catch (Exception ex) {
				fatalDatabseError = true;
				monitor.ReportError ("The add-in database could not be updated. It may be due to file corruption. Try running the setup repair utility", ex);
			}
			
			if (monitor.VerboseLog)
				monitor.Log ("Add-in relations analyzed (" + (int) (DateTime.Now - tim).TotalMilliseconds + " ms)");
			
			SaveAddinHostIndex ();
		}
Beispiel #52
0
        public void ScanFolder(IProgressStatus monitor, string path, string domain, AddinScanResult scanResult)
        {
            path = Util.GetFullPath(path);

            // Avoid folders including each other
            if (!scanResult.VisitFolder(path))
            {
                return;
            }

            if (monitor.LogLevel > 1 && !scanResult.LocateAssembliesOnly)
            {
                monitor.Log("Checking: " + path);
            }

            AddinScanFolderInfo folderInfo;

            if (!database.GetFolderInfoForPath(monitor, path, out folderInfo))
            {
                // folderInfo file was corrupt.
                // Just in case, we are going to regenerate all relation data.
                if (!Directory.Exists(path))
                {
                    scanResult.RegenerateRelationData = true;
                }
            }
            else
            {
                if (folderInfo == null && !Directory.Exists(path))
                {
                    return;
                }
            }

            // if domain is null it means that a new domain has to be created.

            bool sharedFolder = domain == AddinDatabase.GlobalDomain;

            if (folderInfo == null)
            {
                folderInfo = new AddinScanFolderInfo(path);
            }

            if (!sharedFolder && (folderInfo.SharedFolder || folderInfo.Domain != domain))
            {
                // If the folder already has a domain, reuse it
                if (domain == null && folderInfo.RootsDomain != null && folderInfo.RootsDomain != AddinDatabase.GlobalDomain)
                {
                    domain = folderInfo.RootsDomain;
                }
                else if (domain == null)
                {
                    folderInfo.Domain = domain = database.GetUniqueDomainId();
                    scanResult.RegenerateRelationData = true;
                }
                else
                {
                    folderInfo.Domain = domain;
                    scanResult.RegenerateRelationData = true;
                }
            }
            else if (!folderInfo.SharedFolder && sharedFolder)
            {
                scanResult.RegenerateRelationData = true;
            }

            folderInfo.SharedFolder = sharedFolder;

            if (Directory.Exists(path))
            {
                string[] files = Directory.GetFiles(path);

                // First of all, look for .addin files. Addin files must be processed before
                // assemblies, because they may add files to the ignore list (i.e., assemblies
                // included in .addin files won't be scanned twice).
                foreach (string file in files)
                {
                    if (file.EndsWith(".addin.xml") || file.EndsWith(".addin"))
                    {
                        RegisterFileToScan(monitor, file, scanResult, folderInfo);
                    }
                }

                foreach (string file in files)
                {
                    switch (Path.GetExtension(file))
                    {
                    case ".dll":
                    case ".exe":
                        RegisterFileToScan(monitor, file, scanResult, folderInfo);
                        scanResult.AddAssemblyLocation(file);
                        break;

                    case ".addins":
                        ScanAddinsFile(monitor, file, domain, scanResult);
                        break;
                    }
                }
            }
            else if (!scanResult.LocateAssembliesOnly)
            {
                // The folder has been deleted. All add-ins defined in that folder should also be deleted.
                scanResult.RegenerateRelationData = true;
                scanResult.ChangesFound           = true;
                if (scanResult.CheckOnly)
                {
                    return;
                }
                database.DeleteFolderInfo(monitor, folderInfo);
            }

            if (scanResult.LocateAssembliesOnly)
            {
                return;
            }

            // Look for deleted add-ins.

            UpdateDeletedAddins(monitor, folderInfo, scanResult);
        }