/// <summary> /// This method should be called after the object is created. /// </summary> /// <param name="dirs"> /// collection of strings (directory names) /// for each directory in this collection, its sub-directories /// are scanned for plugin.xml /// </param> /// <param name="errorHandler"></param> /// <param name="progressHandler"></param> public static void Init(ICollection dirs, ProgressHandler progressHandler, IPluginErrorHandler errorHandler) { Set pluginSet = new Set(); Hashtable errorPlugins = new Hashtable(); int errCount = 0; int count = 0; float c_max = dirs.Count * 4; bool errBreak = false; if (errorHandler == null) { errorHandler = new SilentPluginErrorHandler(); } // locate plugins foreach (string dir in dirs) { progressHandler("Searching for plugins...\n" + Path.GetFileName(dir), ++count / c_max); //! progressHandler("プラグインを検索中\n"+Path.GetFileName(dir),++count/c_max); if (!File.Exists(Path.Combine(dir, "plugin.xml"))) { continue; // this directory doesn't have the plugin.xml file. } PluginDefinition p = null; try { p = new PluginDefinition(dir); p.loadContributionFactories(); } catch (Exception e) { errCount++; p = PluginDefinition.loadFailSafe(dir); errorPlugins.Add(p, e); errBreak = errorHandler.OnPluginLoadError(p, e); if (errBreak) { break; } else { continue; } } if (pluginMap.Contains(p.name)) { errCount++; // loaded more than once Exception e = new Exception(string.Format( "Plugin \"{0}\" is loaded from more than one place ({1} and {2})", //! "プラグイン「{0}」は{1}と{2}の二箇所からロードされています", p.name, p.dirName, ((PluginDefinition)pluginMap[p.name]).dirName)); errBreak = errorHandler.OnNameDuplicated(pluginMap[p.name] as PluginDefinition, p, e); errorPlugins.Add(p, e); if (errBreak) { break; } else { continue; } } pluginMap.Add(p.name, p); pluginSet.Add(p); } if (errBreak) { Environment.Exit(-1); } {// convert it to an array by sorting them in the order of dependency plugins = new PluginDefinition[pluginSet.Count]; int ptr = 0; PluginDefinition p = null; while (!pluginSet.IsEmpty) { progressHandler("Sorting dependencies...", ++count / c_max); //! progressHandler("依存関係を整理中",++count/c_max); p = (PluginDefinition)pluginSet.GetOne(); try { while (true) { PluginDefinition[] deps = p.getDependencies(); int i; for (i = 0; i < deps.Length; i++) { if (pluginSet.Contains(deps[i])) { break; } } if (i == deps.Length) { break; } else { p = deps[i]; } } } catch (Exception e) { errCount++; errBreak = errorHandler.OnPluginLoadError(p, e); if (!errorPlugins.ContainsKey(p)) { errorPlugins.Add(p, e); } if (errBreak) { break; } } pluginSet.Remove(p); plugins[ptr++] = p; } } if (errBreak) { Environment.Exit(-2); } // load all the contributions foreach (PluginDefinition p in plugins) { progressHandler("Loading contributions...\n" + Path.GetFileName(p.dirName), ++count / c_max); //! progressHandler("コントリビューションをロード中\n"+Path.GetFileName(p.dirName),++count/c_max); try { p.loadContributions(); } catch (Exception e) { errCount++; errBreak = errorHandler.OnPluginLoadError(p, e); if (!errorPlugins.ContainsKey(p)) { errorPlugins.Add(p, e); } if (errBreak) { break; } } } if (errBreak) { Environment.Exit(-3); } // initialize contributions count = (int)c_max; c_max += PublicContributions.Length; foreach (Contribution contrib in PublicContributions) { progressHandler("Initializing contributions...\n" + contrib.BaseUri, ++count / c_max); //! progressHandler("コントリビューションを初期化中\n"+contrib.baseUri,++count/c_max); try { contrib.OnInitComplete(); } catch (Exception e) { errCount++; errBreak = errorHandler.OnContributionInitError(contrib, e); PluginDefinition p = contrib.Parent; if (!errorPlugins.ContainsKey(p)) { errorPlugins.Add(p, e); } if (errBreak) { break; } } } if (errBreak) { Environment.Exit(-4); } {// make sure there's no duplicate id progressHandler("Checking for duplicate IDs...", 1.0f); //! progressHandler("重複IDのチェック中",1.0f); IDictionary dic = new Hashtable(); foreach (Contribution contrib in PublicContributions) { if (dic[contrib.Id] != null) { errCount++; Exception e = new FormatException("ID:" + contrib.Id + " is not unique"); //! Exception e = new FormatException("ID:"+contrib.id+"が一意ではありません"); errBreak = errorHandler.OnContribIDDuplicated(dic[contrib.Id] as Contribution, contrib, e); PluginDefinition p = contrib.Parent; if (!errorPlugins.ContainsKey(p)) { errorPlugins.Add(p, e); } if (errBreak) { break; } } else { dic[contrib.Id] = contrib; } } } if (errBreak) { Environment.Exit(-5); } if (errCount > 0) { if (errorHandler.OnFinal(errorPlugins, errCount)) { Environment.Exit(errCount); } } }