OSDN Git Service

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