OSDN Git Service

AppliStation-all,NaGetTaskクラスをTaskクラスに改名他
[applistation/AppliStation.git] / na-get-lib / NaGet.SubCommands / NaGetDownloadToCache.cs
1 using System;
2 using System.Collections.Generic;
3 using NaGet.Packages.Install;
4 using NaGet.Packages;
5 using NaGet.Net;
6 using NaGet.Tasks;
7
8 namespace NaGet.SubCommands
9 {
10         public class NaGetDownloadToCache : NaGetTaskSet
11         {
12                 private bool done = false;
13                 
14                 private int currentTaskSetIndex = -1;
15                 
16                 private PackageListsManager pkgListMan;
17                 
18                 /// <summary>
19                 /// ダウンロードに使うダウンローダオブジェクト
20                 /// </summary>
21                 public Downloader Downloader {
22                         get {
23                                 if (downloader == null) {
24                                         downloader = new Downloader();
25                                         downloader.DownloadEventRaised += delegate(object sender, DownloadEventArgs e) {
26                                                 if (e.Type == DownloadEventType.DOWNLOADING && e.ProgressPercent > 0) {
27                                                         RaiseTaskSetEvent(NaGetTaskSetEventType.PING, string.Empty, GetProgressPercent(NaGetTaskSetEventType.PING, e.ProgressPercent));
28                                                 }
29                                         };
30                                 }
31                                 return downloader;
32                         }
33                 }
34                 
35                 private Downloader downloader;
36                 
37                 private bool packageInstallerDownloaded = false;
38                 
39                 public override bool Cancelable {
40                         get { return ! done; }
41                 }
42                 
43                 /// <summary>
44                 /// ダウンロードするパッケージ
45                 /// </summary>
46                 public Installation[] Installations;
47                 
48                 /// <summary>
49                 /// コンストラクタ
50                 /// </summary>
51                 /// <param name="pkgs">インストールするパッケージ</param>
52                 public NaGetDownloadToCache(PackageListsManager pkgListMan, Package[] pkgs)
53                         : this(pkgListMan, Installation.ConvertInstallations(pkgs))
54                 {
55                 }
56                 
57                 /// <summary>
58                 /// コンストラクタ
59                 /// </summary>
60                 /// <param name="installations">インストール処理の配列</param>
61                 public NaGetDownloadToCache(PackageListsManager pkgMan, Installation[] installations)
62                 {
63                         pkgListMan = pkgMan;
64                         
65                         Installations = installations;
66                         initializeMainTaskSetNames();
67                 }
68                 
69                 private void initializeMainTaskSetNames()
70                 {
71                         List<string> taskSetNames = new List<string>();
72                         
73                         for (int i =0; i < Installations.Length; i++) {
74                                 taskSetNames.Add(string.Format("取得: {0}", Installations[i].ToString()));
75                                 taskSetNames.Add(string.Format("ウイルススキャン: {0}", Installations[i].ToString()));
76                         }
77                         taskSetNames.Add("インストーラーの検証");
78                         taskSetNames.Add(string.Format("リスト更新: {0}", NaGet.Env.ArchiveInstalledPackageListFile));
79                         taskSetNames.Add(string.Format("リスト更新: {0}", NaGet.Env.SystemInstalledPackageListFile));
80                         
81                         TaskSetNames = taskSetNames.ToArray();
82                 }
83                                 
84                 public override void Run()
85                 {
86                         currentTaskSetIndex = 0;
87                         RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED, "インストール処理開始");
88                         
89                         {
90                                 // ハッシュ非適合なインストーラの表
91                                 List<Installation> invalidInstallers = null;
92                                 
93                                 do {
94                                         currentTaskSetIndex = 0;
95                                         packageInstallerDownloaded = false;
96                                         
97                                         runDownloadAndVirusCheckInstallers();
98                                         if (done) return; // もしrunDownloadInstallers()内でエラー終了していたなら終了
99                                         
100                                         packageInstallerDownloaded = true;
101                                         
102                                         
103                                         RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED_TASKSET, TaskSetNames[currentTaskSetIndex]);
104                                         
105                                         // ハッシュの壊れているインストーラーを取得
106                                         invalidInstallers = runCheckHashForInstaller();
107                                         
108                                         // ハッシュが壊れているときの対策
109                                         if (invalidInstallers.Count > 0) {
110                                                 System.Text.StringBuilder invalidInstallerNames = new System.Text.StringBuilder();
111                                                 foreach (Installation invalidInst in invalidInstallers) {
112                                                         invalidInstallerNames.AppendFormat(" - {0}\n", invalidInst.ToString());
113                                                 }
114                                                 
115                                                 string msg = string.Format("以下の{0}個のパッケージでファイルが壊れている可能性があります。\n{1}\nダウンロードし直しますか?",
116                                                                            invalidInstallers.Count, invalidInstallerNames.ToString());
117                                                 NaGetTaskQueryResult result = NaGetTaskQueryResult.CANCEL;
118                                                 
119                                                 if (!cancelCalled) {
120                                                         result = RaiseTaskSetQueryEvent(msg, NaGetTaskQueryResult.CONTINUE
121                                                                                         | NaGetTaskQueryResult.CANCEL);
122                                                 }
123                                                 
124                                                 switch (result) {
125                                                         case NaGetTaskQueryResult.CONTINUE:
126                                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.INFO, "ダウンロード処理を再試行");
127                                                                 
128                                                                 foreach (Installation invalidInst in invalidInstallers) {
129                                                                         invalidInst.RemoveDownloadedFile();
130                                                                 }
131                                                                 
132                                                                 break;
133                                                         //case NaGetTaskQueryResult.CANCEL:
134                                                         default:
135                                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.CANCELED, "パッケージのダウンロード処理がキャンセルされました");
136                                                                 done = true;
137                                                                 return;
138                                                 }
139                                         }
140                                         
141                                         // もしハッシュが不適合なソフトがあるならばダウンロード処理からやり直す
142                                 } while (invalidInstallers == null || invalidInstallers.Count > 0);
143                                 RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED_TASKSET, TaskSetNames[currentTaskSetIndex]);
144                                 currentTaskSetIndex ++;
145                         }
146                         
147                         runLocalUpdate();
148                         
149                         done = true;
150                         
151                         RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED, "終了", 100);
152                 }
153                 
154                 
155                 /// <summary>
156                 /// 処理内容のダウンロード・ウイルススキャン部分のサブルーチン
157                 /// </summary>
158                 private void runDownloadAndVirusCheckInstallers()
159                 {
160                         using (DownloadScanner scanner = new DownloadScanner()) {
161                                 scanner.Init();
162                                 foreach (Installation inst in Installations) {
163                                         RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED_TASKSET, TaskSetNames[currentTaskSetIndex]);
164                                         
165                                         if (! inst.Downloaded) {
166                                                 try {
167                                                         inst.Download(Downloader);
168                                                 } catch (TaskCanceledException) {
169                                                         RaiseTaskSetEvent(NaGetTaskSetEventType.CANCELED, "インストーラーのダウンロード処理がキャンセルされました");
170                                                         done = true;
171                                                         return;
172                                                 } catch (System.Net.WebException e) {
173                                                         RaiseTaskSetEvent(NaGetTaskSetEventType.WARNING, e.Message);
174                                                         if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable()) {
175                                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, "ネットワークに接続されていません。");
176                                                         } else {
177                                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, "ネットワークに接続できませんでした。ネットワークが切断されているか、ファイアウォールによって遮断された可能性があります。");
178                                                         }
179                                                         done = true;
180                                                         return;
181                                                 } catch (Exception e) {
182                                                         RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, e.Message);
183                                                         done = true;
184                                                         return;
185                                                 }
186                                         }
187                                         
188                                         if (! inst.Downloaded) { // ダウンロードが完了せずに終わった=失敗=エラー
189                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, string.Format("{0}のインストーラーファイルを正常にダウンロードできませんでした", inst.ToString()));
190                                                 done = true;
191                                                 return;
192                                         }
193                                         RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED_TASKSET, TaskSetNames[currentTaskSetIndex]);
194                                         currentTaskSetIndex ++;
195                                         
196                                         RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED_TASKSET, TaskSetNames[currentTaskSetIndex]);
197                                         if (! NaGet.Env.EnableScanInstallerFile) {
198                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.INFO, "ウイルススキャンを行わない設定のため、ダウンロードしたファイルはウイルススキャンされませんでした");
199                                         } else if (!scanner.HasScanner) {
200                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.INFO, "ダウンロードしたファイルはウイルススキャンされませんでした(ウイルススキャンソフトが検出できませんでした)");
201                                         } else {
202                                                 try {
203                                                         DownloadScannerResult result = inst.ScanInstallerFile(scanner);
204                                                         
205                                                         switch (result) {
206                                                                 case DownloadScannerResult.ScannerNotFound:
207                                                                         RaiseTaskSetEvent(NaGetTaskSetEventType.INFO, "ダウンロードしたファイルはウイルススキャンされませんでした(ウイルススキャンソフトが検出できませんでした)");
208                                                                         break;
209                                                                 case DownloadScannerResult.InfectedAndCleaned:
210                                                                         RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR,
211                                                                                   "インストーラーファイルからウイルス感染が検出されたため、削除されました。");
212                                                                         done = true;
213                                                                         return;
214                                                                 case DownloadScannerResult.InfectedButNotCleaned:
215                                                                         RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR,
216                                                                                   "インストーラーファイルからウイルス感染が検出されました。");
217                                                                         done = true;
218                                                                         break;
219                                                                 case DownloadScannerResult.ErrorNotFound:
220                                                                         throw new System.IO.FileNotFoundException(string.Empty);
221                                                                         //break;
222                                                         }
223                                                         
224                                                 } catch (System.Runtime.InteropServices.COMException ex) {
225                                                         RaiseTaskSetEvent(NaGetTaskSetEventType.WARNING,
226                                                                           string.Format("{0} (E{1})", ex.Message, ex.ErrorCode));
227                                                 } catch (System.IO.FileNotFoundException ex) {
228                                                         if (ex.InnerException is System.Runtime.InteropServices.COMException) {
229                                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.WARNING,
230                                                                                   string.Format("{0} (E{1})", ex.InnerException.Message, ((System.Runtime.InteropServices.COMException) ex.InnerException).ErrorCode));
231                                                         }
232                                                         RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, "インストーラーファイルがウイルススキャナーによって削除されました。");
233                                                         done = true;
234                                                         return;
235                                                 }
236                                         }
237                                         RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED_TASKSET, TaskSetNames[currentTaskSetIndex]);
238                                         currentTaskSetIndex ++;
239                                         
240                                         if (cancelCalled) {
241                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.CANCELED, "パッケージのインストール処理がキャンセルされました");
242                                                 done = true;
243                                                 return;
244                                         }
245                                 }
246                         }
247                 }
248                 
249                 /// <summary>
250                 /// ダウンロードしたパッケージが整合したか否かハッシュでチェック
251                 /// </summary>
252                 /// <returns>整合しなかったインストーラーのリスト</returns>
253                 private List<Installation> runCheckHashForInstaller()
254                 {
255                         List<Installation> invalidInstallers = new List<Installation>();
256                         
257                         int i = 0;
258                         foreach (Installation inst in Installations) {
259                                 float percent = (CurrentTaskSetIndex+((float)i / Installations.Length))*100f/TaskSetNames.Length;
260                                 
261                                 if (inst.GetRegisteredHashCount() > 0) {
262                                         RaiseTaskSetEvent(NaGetTaskSetEventType.INFO, "検証: "+inst.ToString(), percent);
263                                         
264                                         if (inst.IsInstallablePackage() && inst.VerifyHashValues() == false) {
265                                                 invalidInstallers.Add(inst);
266                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.WARNING, "検証: "+inst.ToString() + " 非整合", percent);
267                                         } else {
268                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.INFO, "検証: "+inst.ToString() + " OK", percent);
269                                         }
270                                 }
271                                 i++;
272                         }
273                         
274                         return invalidInstallers;
275                 }
276                 
277                 private void runLocalUpdate()
278                 {
279                         // インストールトリストの更新
280                         RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED_TASKSET, TaskSetNames[currentTaskSetIndex]);
281                         pkgListMan.DetectInstalledPkgs();
282                         pkgListMan.SaveInstalledPackageList();
283                         RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED_TASKSET, TaskSetNames[currentTaskSetIndex]);
284                         currentTaskSetIndex++;
285                 
286                         // システムにインストールされているリストの更新
287                         RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED_TASKSET, TaskSetNames[currentTaskSetIndex]);
288                         pkgListMan.DetectSystemInstalledPkgs();
289                         pkgListMan.SaveSystemInstalledPackageList();
290                         RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED_TASKSET, TaskSetNames[currentTaskSetIndex]);
291                         currentTaskSetIndex++;
292                 }
293                 
294                 public override bool Done {
295                         get { return done; }
296                 }
297                 
298                 public override int CurrentTaskSetIndex {
299                         get { return currentTaskSetIndex; }
300                 }
301                 
302                 private bool cancelCalled = false;
303                 
304                 public override bool Cancel()
305                 {
306                         cancelCalled = true;
307                         if (! packageInstallerDownloaded) {
308                                 return Downloader.Cancel();
309                         } else return true;
310                 }
311         }
312 }