# 機能設計書 58-ファイルパラメータ

## 概要

本ドキュメントは、Jenkinsのファイルパラメータ（FileParameterDefinition）機能の設計を記述する。ファイルパラメータは、ビルド実行時にユーザーがファイルをアップロードし、そのファイルをビルドのワークスペースで使用できるようにするための機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：ビルド実行時に、外部で作成された設定ファイル、テストデータ、バイナリファイルなどをビルドプロセスに渡したい場面がある。ファイルパラメータにより、ユーザーはWebインターフェースからファイルをアップロードし、ビルドのワークスペースに自動的に配置することができる。これにより、動的なビルド入力が可能となる。

**機能の利用シーン**：
- 設定ファイル（config.xml等）をビルドに渡す際
- テストデータファイルをアップロードする際
- 署名キーやライセンスファイルをビルドに渡す際
- 外部で生成されたアーティファクトを使用する際

**主要な処理内容**：
1. パラメータ名（ファイル配置場所の名前）の設定
2. ファイルアップロードフォームの表示
3. アップロードされたファイルからFileParameterValue生成
4. ビルド開始時にワークスペースへファイル配置
5. CLIからの標準入力経由でのファイル受け取り

**関連システム・外部連携**：
- ParameterDefinition: 親クラス（SimpleParameterDefinitionではない）
- FileParameterValue: 実際のファイルデータを保持するクラス
- Apache Commons FileUpload: ファイルアップロード処理
- Pipeline DSL: `file`または`fileParam`シンボルで参照

**権限による制御**：パラメータ入力にはJob.BUILD権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 12 | ジョブ設定 | 主機能 | ファイルパラメータの定義 |
| 20 | パラメータ入力 | 主機能 | ファイルアップロードフォームの表示 |

## 機能種別

ファイル処理 / データ入力 / パラメータ処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | String | Yes | パラメータの名前（ワークスペースでの配置場所） | 非null |
| description | String | No | パラメータの説明 | - |

### 入力データソース

- ジョブ設定画面: FileParameterDefinitionのconfig.jelly
- ビルド実行画面: FileParameterDefinitionのindex.jelly（ファイル入力フィールド）
- CLI: 標準入力からのファイルデータ
- REST API: multipart/form-dataでのファイルアップロード

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| FileParameterValue | FileParameterValue | アップロードされたファイルを保持するオブジェクト |
| location | String | ワークスペース内のファイル配置パス |
| originalFileName | String | アップロード時の元のファイル名 |

### 出力先

- XMLファイル: ジョブのconfig.xml内に定義を永続化
- ワークスペース: ビルド開始時に`${name}`パスにファイルを配置
- 一時ファイル: アップロード時にサーバー側で一時保存

## 処理フロー

### 処理シーケンス

```
1. ジョブ設定でFileParameterDefinitionを追加
   └─ name（配置場所）, descriptionを設定
2. パラメータ定義の保存
   └─ ジョブのconfig.xmlに永続化
3. ビルド実行時のパラメータ入力
   └─ ファイル選択フィールドを表示
4. ファイルアップロード処理
   └─ createValue(req, jo)またはcreateValue(req)でFileParameterValue生成
5. 一時ファイル保存
   └─ アップロードされたファイルをサーバーに一時保存
6. ビルド開始時のファイル配置
   └─ FileParameterValue.buildEnvironment()でワークスペースに配置
7. ビルド終了後のクリーンアップ
   └─ 一時ファイルの削除
```

### フローチャート

```mermaid
flowchart TD
    A[パラメータ入力画面] --> B[ファイル選択]
    B --> C{ファイル選択?}
    C -->|Yes| D[ファイルアップロード]
    C -->|No| E[null返却]
    D --> F[getFileName処理]
    F --> G[パス部分を除去]
    G --> H[FileParameterValue生成]
    H --> I[一時ファイル保存]
    I --> J[ビルドキュー追加]
    J --> K[ビルド開始]
    K --> L[ワークスペースにファイル配置]
    L --> M[ビルド実行]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-58-01 | 配置場所 | nameの値がワークスペース内のファイル配置パスとなる | ビルド開始時 |
| BR-58-02 | パス除去 | アップロード時のフルパスからファイル名のみを抽出 | ファイル名処理時 |
| BR-58-03 | null許容 | ファイル未選択の場合はnullを返却 | createValue時 |
| BR-58-04 | デフォルト値なし | FileParameterDefinitionはgetDefaultParameterValue()をオーバーライドしない（nullを返却） | 常時 |

### 計算ロジック

ファイル名抽出:
- `possiblyPathName.substring(possiblyPathName.lastIndexOf('/') + 1)`: Unixパス除去
- `possiblyPathName.substring(possiblyPathName.lastIndexOf('\\') + 1)`: Windowsパス除去

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

本機能はデータベースを直接操作しない。

### ファイル永続化

| 操作 | 対象ファイル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| パラメータ定義保存 | `jobs/{jobName}/config.xml` | WRITE | FileParameterDefinitionとして保存 |
| 一時ファイル保存 | `{tmpdir}/jenkins*.parameter` | WRITE | アップロードファイルの一時保存 |
| ワークスペース配置 | `workspace/{name}` | WRITE | ビルド時のファイル配置 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ServletException | ファイルアップロードエラー | nullを返却、エラーログ出力 |
| - | IOException | ファイル読み取りエラー | nullを返却、エラーログ出力 |
| - | IllegalArgumentException | パラメータ名がnull | 例外スロー（親クラスで処理） |

### リトライ仕様

リトライは行わない。エラー発生時はnullを返却してビルドをスキップ可能。

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

本機能はトランザクション管理を行わない。

## パフォーマンス要件

- ファイルアップロード: ファイルサイズに比例（大きなファイルは時間がかかる）
- 一時ファイル作成: O(n)（ファイルサイズに比例）

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

- アップロードされたファイルはワークスペースに配置されるため、実行可能ファイルの注入に注意
- ファイルサイズ制限はStaplerの設定に依存
- 一時ファイルは適切に削除されるべき
- パストラバーサル攻撃を防ぐため、nameの値はサニタイズ推奨

## 備考

- FileParameterDefinitionはSimpleParameterDefinitionを継承していない（createValue(String)をサポートしないため）
- Pipeline DSLでは`file(name: 'CONFIG', description: 'Config file')`で定義
- CLIでは標準入力からファイルを読み取る特殊処理がある

---

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

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

### 推奨読解順序

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

まず、FileParameterDefinitionのクラス構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | FileParameterDefinition.java | `core/src/main/java/hudson/model/FileParameterDefinition.java` | クラス定義、ParameterDefinition直接継承 |
| 1-2 | ParameterDefinition.java | `core/src/main/java/hudson/model/ParameterDefinition.java` | 親クラスの機能 |

**読解のコツ**: FileParameterDefinitionは`ParameterDefinition`を直接継承し、`SimpleParameterDefinition`を継承していない。これはファイルアップロードが単純な文字列変換では表現できないため。

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

コンストラクタとcreateValueメソッドを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | FileParameterDefinition.java | `core/src/main/java/hudson/model/FileParameterDefinition.java` | コンストラクタ、createValue()メソッド群 |

**主要処理フロー**:
1. **57-60行目**: `@DataBoundConstructor`付きコンストラクタ（name必須）
2. **62-65行目**: 2引数コンストラクタ（name, description）
3. **68-73行目**: `createValue(StaplerRequest2, JSONObject)`でJSONからバインド
4. **90-107行目**: `createValue(StaplerRequest2)`でmultipartからファイル取得
5. **109-116行目**: `getFileName()`でパス部分を除去

#### Step 3: CLI処理を理解する

コマンドラインからのファイル入力処理を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FileParameterDefinition.java | `core/src/main/java/hudson/model/FileParameterDefinition.java` | createValue(CLICommand, String)メソッド |

**主要処理フロー**:
- **120-136行目**: `createValue(CLICommand, String)`でCLI処理
- **122行目**: 一時ファイル作成（`Files.createTempFile("jenkins", "parameter")`）
- **125行目**: 空文字列の場合は標準入力から読み取り
- **128行目**: それ以外はcheckChannel()でエラー

#### Step 4: Descriptorを理解する

パラメータ型のメタデータを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | FileParameterDefinition.java | `core/src/main/java/hudson/model/FileParameterDefinition.java` | DescriptorImpl内部クラス |

**主要処理フロー**:
- **75行目**: `@Extension @Symbol({"file", "fileParam"})`でシンボル名定義
- **77-81行目**: `getDisplayName()`で表示名返却
- **83-86行目**: `getHelpFile()`でヘルプファイルパス返却

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

```
パラメータ入力フォーム送信
    │
    ├─ FileParameterDefinition.createValue(req, jo)
    │      │
    │      └─ req.bindJSON(FileParameterValue.class, jo)
    │             │
    │             └─ FileParameterValue生成
    │
    └─ FileParameterDefinition.createValue(req)
           │
           ├─ req.getFileItem2(getName())
           │      │
           │      └─ FileItem取得
           │
           └─ getFileName()
                  │
                  └─ パス部分除去
                         │
                         └─ FileParameterValue生成
```

### データフロー図

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

ファイル選択           FileParameterDefinition         一時ファイル
(index.jelly)  ───▶    .createValue()          ───▶    (tmpdir)
      │                      │                              │
      ▼                      ▼                              ▼
FileItem               getFileName()                ワークスペース
(multipart)            (パス除去)                   ${name}にコピー
      │                                                     │
      ▼                                                     ▼
FileParameterValue                                  ビルドで使用
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| FileParameterDefinition.java | `core/src/main/java/hudson/model/FileParameterDefinition.java` | ソース | ファイルパラメータ定義 |
| FileParameterValue.java | `core/src/main/java/hudson/model/FileParameterValue.java` | ソース | ファイルパラメータ値 |
| ParameterDefinition.java | `core/src/main/java/hudson/model/ParameterDefinition.java` | ソース | 親クラス |
| config.jelly | `core/src/main/resources/hudson/model/FileParameterDefinition/config.jelly` | ビュー | 設定フォーム |
| index.jelly | `core/src/main/resources/hudson/model/FileParameterDefinition/index.jelly` | ビュー | 入力フォーム（ファイル選択） |
