# 機能設計書 2-プラグインマネージャー

## 概要

本ドキュメントは、Jenkinsのプラグイン管理機能であるプラグインマネージャー（hudson.PluginManager）の機能設計を記述する。プラグインのインストール・更新・削除・有効化/無効化を一元的に管理し、Jenkinsの拡張性を実現する中核コンポーネントである。

### 本機能の処理概要

プラグインマネージャーは、JenkinsのPluginWrapper群を管理し、プラグインのライフサイクル全体を制御する。

**業務上の目的・背景**：Jenkinsの基本機能だけでは対応できない多様なビルド要件（Git連携、Docker対応、Slack通知等）に対応するため、プラグインによる拡張が不可欠である。プラグインマネージャーは数千種類のプラグインを安全かつ効率的に管理することで、Jenkinsの柔軟性と拡張性を実現する。

**機能の利用シーン**：新規プラグインの追加時、既存プラグインのアップデート時、不要プラグインの削除時、プラグインの依存関係解決時、プラグインに起因する問題発生時の無効化操作など。

**主要な処理内容**：
1. プラグイン（.hpiまたは.jpiファイル）のロードと初期化
2. プラグインの依存関係の解決と循環依存の検出
3. プラグインのインストール・アップデート（UpdateCenter経由）
4. プラグインの有効化・無効化
5. プラグインのアンインストール（削除マーカー作成）
6. カスタムClassLoaderによるプラグインクラスの分離
7. UberClassLoaderによる全プラグインへの統一アクセス提供

**関連システム・外部連携**：UpdateCenter（更新情報取得）、HTTPプロキシ（ダウンロード時）、ファイルシステム（プラグインファイル管理）。

**権限による制御**：ADMINISTER権限を持つユーザーのみがプラグインの管理操作（インストール、アップデート、削除、有効化/無効化）を実行可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 37 | プラグイン管理トップ | 主画面 | プラグイン管理のナビゲーション |
| 38 | インストール済みプラグイン | 主画面 | インストール済みプラグインの一覧表示・管理 |
| 39 | 利用可能なプラグイン | 主画面 | インストール可能プラグインの検索・一覧表示 |
| 40 | 更新可能なプラグイン | 主画面 | 更新可能プラグインの一覧表示 |
| 41 | プラグイン詳細設定 | 主画面 | プラグインの詳細設定（アップデートサイト等） |
| 42 | 更新センター | 参照画面 | プラグインダウンロード・インストール状況の表示 |
| 51 | セットアップウィザード | 参照画面 | 推奨プラグインのインストール |

## 機能種別

管理機能 / プラグイン管理 / 拡張機能管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| pluginFile | FileItem | Yes | アップロードするプラグインファイル | .hpiまたは.jpi拡張子 |
| pluginName | String | Yes | プラグインの短縮名（ID） | 英数字とハイフン |
| version | String | No | インストールするバージョン | セマンティックバージョン形式 |
| dynamicLoad | boolean | No | 動的ロードを試行するか | true/false |

### 入力データソース

- plugins ディレクトリ: $JENKINS_HOME/plugins/ 配下の.hpi/.jpiファイル
- UpdateSite: 更新サイトからのプラグインメタデータ（JSON）
- Web画面: プラグイン管理画面からのユーザー操作
- REST API: プラグイン管理API経由のリクエスト
- CLI: InstallPluginCommand等のCLIコマンド

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| plugins | List<PluginWrapper> | ロード済みプラグイン一覧 |
| activePlugins | List<PluginWrapper> | 有効化されているプラグイン |
| failedPlugins | List<FailedPlugin> | ロード失敗したプラグイン |
| uberClassLoader | ClassLoader | 全プラグインを包含するクラスローダー |

### 出力先

- plugins ディレクトリ: プラグインファイル、.disabled マーカー
- Webインターフェース: プラグイン管理画面
- REST API: /pluginManager/api/json

## 処理フロー

### 処理シーケンス

```
1. Jenkins起動時のプラグインロード
   ├─ plugins ディレクトリスキャン
   ├─ 各プラグインのマニフェスト解析
   ├─ 依存関係グラフの構築
   ├─ トポロジカルソートによるロード順決定
   └─ 各プラグインの初期化
2. プラグインインストール
   ├─ UpdateCenterからダウンロード
   ├─ 依存プラグインの自動解決
   ├─ ファイル配置
   └─ 動的ロードまたは再起動要求
3. プラグイン無効化
   ├─ .disabled ファイル作成
   └─ 再起動要求
4. プラグインアンインストール
   ├─ .jpi.disabled 作成
   └─ 再起動後にファイル削除
```

### フローチャート

```mermaid
flowchart TD
    A[プラグインインストール要求] --> B{UpdateCenter経由?}
    B -->|Yes| C[UpdateCenterからダウンロード]
    B -->|No| D[ファイルアップロード]
    C --> E[依存関係チェック]
    D --> E
    E --> F{依存関係解決可能?}
    F -->|Yes| G[pluginsディレクトリに配置]
    F -->|No| H[エラー: 依存関係未解決]
    G --> I{動的ロード可能?}
    I -->|Yes| J[動的ロード実行]
    I -->|No| K[再起動要求フラグ設定]
    J --> L[プラグイン初期化]
    K --> M[完了（要再起動）]
    L --> N[完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 依存関係解決 | 依存プラグインが存在しない場合はロードしない | プラグインロード時 |
| BR-002 | 循環依存検出 | 循環依存が検出された場合はエラー | 依存関係解析時 |
| BR-003 | バージョン互換性 | 要求バージョンを満たさない依存はエラー | 依存関係チェック時 |
| BR-004 | 必須プラグイン保護 | コアに必須のプラグインは削除不可 | アンインストール時 |
| BR-005 | 動的ロード制限 | 一部プラグインは動的ロード非対応 | インストール時 |

### 計算ロジック

- 依存関係解決: CyclicGraphDetectorによる循環検出とトポロジカルソート
- バージョン比較: VersionNumber.compareTo()によるセマンティックバージョン比較

## データベース操作仕様

Jenkinsはファイルベースの永続化を使用し、RDBMSは使用しない。

### ファイル操作一覧

| 操作 | 対象ファイル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ロード | plugins/*.hpi, *.jpi | 読み取り | プラグインアーカイブの読み込み |
| インストール | plugins/*.jpi | 書き込み | 新規プラグインの配置 |
| 無効化 | plugins/*.jpi.disabled | 作成 | 無効化マーカー作成 |
| 削除 | plugins/*.jpi | 削除 | プラグインファイル削除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | MissingDependencyException | 必須依存プラグインが見つからない | 依存プラグインをインストール |
| - | CycleDetectedException | プラグイン間で循環依存が発生 | 循環を解消するプラグイン削除 |
| - | IOException | プラグインファイルの読み書き失敗 | ファイルシステム権限確認 |
| - | RestartRequiredException | 動的ロード不可能なプラグイン | Jenkins再起動 |

### リトライ仕様

ダウンロード失敗時はCHECK_UPDATE_ATTEMPTS回（デフォルト1回）リトライ、リトライ間隔はCHECK_UPDATE_SLEEP_TIME_MILLIS（デフォルト1000ms）。

## トランザクション仕様

ファイルベース操作のため、RDBMSトランザクションは存在しない。プラグインインストールはアトミック性を保証するため、一時ファイルに書き込み後にリネームする方式を採用。

## パフォーマンス要件

- プラグインロード: 数十プラグインで数秒〜数十秒
- 動的ロード: 単一プラグインで数秒以内
- UberClassLoader: 全プラグインのクラスを効率的にロード

## セキュリティ考慮事項

- 権限チェック: ADMINISTER権限が必要
- 署名検証: プラグインの署名を検証（オプション）
- 信頼されたソース: 公式UpdateCenterからのダウンロードを推奨
- カスタムプラグイン: 手動アップロードは管理者責任

## 備考

- プラグインの依存関係は MANIFEST.MF の Plugin-Dependencies 属性で定義
- 動的ロードはYesNoMaybe列挙型で対応状況を表現
- ClassLoader階層: Jenkins ClassLoader -> UberClassLoader -> 個別プラグインClassLoader

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

プラグインを表現するPluginWrapperクラスを理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | PluginManager.java | `core/src/main/java/hudson/PluginManager.java` | 抽象クラスとしての基本構造、主要フィールド（plugins, activePlugins, failedPlugins, uberClassLoader）を確認 |
| 1-2 | PluginWrapper.java | `core/src/main/java/hudson/PluginWrapper.java` | 個々のプラグインを表現するクラス、Dependencyの構造 |

**読解のコツ**: PluginManagerは抽象クラスで、実際の実装はLocalPluginManagerにある。まず抽象クラスでインターフェースを把握してから実装を読む。

#### Step 2: エントリーポイントを理解する

プラグインロードの開始点を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | PluginManager.java | `core/src/main/java/hudson/PluginManager.java` | createDefault()メソッド（299行目〜）でカスタムPluginManagerの生成ロジックを確認 |
| 2-2 | LocalPluginManager.java | `core/src/main/java/hudson/LocalPluginManager.java` | デフォルト実装のコンストラクタ |

**主要処理フロー**:
1. **299-300行目**: createDefault()でカスタムクラスまたはLocalPluginManager生成
2. **PMConstructor enum**: コンストラクタ探索の優先順位（JENKINS, SC_FILE2, SC_FILE, FILE）

#### Step 3: プラグインロード処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | PluginManager.java | `core/src/main/java/hudson/PluginManager.java` | initTasks()メソッドでReactorタスクとしてのロード処理 |

#### Step 4: 依存関係解決を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | CyclicGraphDetector.java | `core/src/main/java/hudson/util/CyclicGraphDetector.java` | 循環依存検出アルゴリズム |
| 4-2 | PluginWrapper.Dependency | `core/src/main/java/hudson/PluginWrapper.java` | 依存関係の表現（shortName, version, optional） |

### プログラム呼び出し階層図

```
Jenkins.constructor()
    │
    ├─ PluginManager.createDefault(this)
    │      └─ new LocalPluginManager(jenkins)
    │
    └─ executeReactor(pluginManager.initTasks())
           │
           ├─ PLUGINS_LISTED マイルストーン
           │      └─ pluginsディレクトリスキャン
           │
           ├─ PLUGINS_PREPARED マイルストーン
           │      ├─ 依存関係解決
           │      └─ CyclicGraphDetector実行
           │
           └─ PLUGINS_STARTED マイルストーン
                  ├─ 各PluginWrapperの初期化
                  └─ Plugin.start()呼び出し
```

### データフロー図

```
[入力]                      [処理]                           [出力]

plugins/*.jpi ──────────▶ JarFile解析 ─────────────────▶ PluginWrapper
                                │
                                ▼
MANIFEST.MF ───────────────▶ 依存関係解析 ─────────────▶ 依存グラフ
                                │
                                ▼
UpdateSite JSON ───────────▶ UpdateCenter ──────────────▶ 更新可能プラグイン一覧
                                │
                                ▼
プラグインダウンロード ────▶ ファイル配置 ─────────────▶ 再起動要求
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| PluginManager.java | `core/src/main/java/hudson/PluginManager.java` | ソース | プラグインマネージャー抽象クラス |
| LocalPluginManager.java | `core/src/main/java/hudson/LocalPluginManager.java` | ソース | デフォルト実装 |
| PluginWrapper.java | `core/src/main/java/hudson/PluginWrapper.java` | ソース | プラグインのラッパークラス |
| Plugin.java | `core/src/main/java/hudson/Plugin.java` | ソース | プラグイン基底クラス |
| ClassicPluginStrategy.java | `core/src/main/java/hudson/ClassicPluginStrategy.java` | ソース | プラグインロード戦略 |
| index.jelly | `core/src/main/resources/hudson/PluginManager/index.jelly` | テンプレート | プラグイン管理画面 |
| installed.jelly | `core/src/main/resources/hudson/PluginManager/installed.jelly` | テンプレート | インストール済み一覧 |
