Eclipseプラグイン開発でのパス取得とかファイル操作とかのやり方

Eclipseのプラグイン開発における小ネタ。

## ファイル操作

プラグイン開発ではjava.io.Fileを使わずに、IFileの実装クラスであるorg.eclipse.core.internal.resources.Fileのインスタンスを作成して操作する。

```java
// ワークスペースのルートを取得して、プロジェクトのファイルのFileインスタンスを作成する。
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
IFile scopeFile  = root.getFile(new Path("/RemoteSystemsTempFiles/tempFileName"));
```

ちなみにgetFileに渡すPathは、プロジェクト名とリソース名を含んでいないと、以下のエラーになる。

```java
java.lang.IllegalArgumentException: Path must include project and resource name: /tempFileName
	at org.eclipse.core.runtime.Assert.isLegal(Assert.java:63)
	at org.eclipse.core.internal.resources.Workspace.newResource(Workspace.java:2137)
	at org.eclipse.core.internal.resources.Container.getFile(Container.java:208)
	<ResourcesPlugin.getWorkspace().getRoot().getFile(new Path("/tempFileName"));の実行箇所>
```


### 具体例

例えば、アクティブなエディタのプロジェクトルートを取得し、その配下のファイル情報を作成する場合は、以下のようなコードになる。

```java
// アクティブエディタ（編集中のファイル）の情報を取得する。
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
IEditorPart editor = window.getActivePage().getActiveEditor();
ITextEditor textEditor = (ITextEditor)editor;

// エディタ情報をもとに、編集中のファイルが属するプロジェクト情報を取得する。
IFileEditorInput editorInput = (IFileEditorInput)textEditor.getEditorInput();
IFile file = editorInput.getFile();
IProject project = file.getProject();

// プロジェクトのフルパスに、取得したいファイルのプロジェクトルートからの相対パスを追加して、
// ファイル情報を取得する。
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
IPath path = project.getFullPath().append("tempFileName");
IFile file  = root.getFile(path);
```


## パスの操作

Pathインスタンスにパスを追加する場合はappendメソッドを使う。
**ただし、StringBuilderのappendなどとは違い、appendメソッドが返すのは新規Pathインスタンスなので、呼ぶだけでは情報が捨てられてしまう。**

逆に削除する場合はremoveLastSegmentsメソッドを使う。
合わせたサンプルは以下。

```java
// 同一階層の別ファイルにパスを変更
IPath newPath = path.removeLastSegments(1).append("otherFileName");
```


## ファイルの作成、更新、削除

上記手順でFileインスタンスは取得できたので、それに対して作成等の操作を行うサンプルは以下。

```java
try (InputStream in = new ByteArrayInputStream("hoge".getBytes())){

	if (file.exists()) {
		// 上書き
		file.setContents(in, true, true, null);
	} else {
		// 新規作成
		file.create(in, true, null);
	}

	// 削除
	file.delete(false, null);
	
} catch (CoreException | IOException e) {
	e.printStackTrace();
}
```


## importとライブラリ

### import文

今回の実装を記述した場合に書くimport文は以下。

```java
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;
```

### 依存解決

plugin.xmlを「プラグインのマニフェスト・エディター」で開き、依存解決タブに以下を追加する。
※最小バージョンを指定する必要はない。

- org.eclipse.ui
- org.eclipse.core.runtime
- org.eclipse.core.resources
- org.eclipse.jdt.core
- org.eclipse.ui.ide
- org.eclipse.ui.editors
- org.eclipse.jface.text


# 結局わからなかったこと

以下は結局わからなかった。

### workspace直下にフォルダ、ファイルを作成する方法

先に触れている通り、getFileはプロジェクト名とリソース名を指定していなければエラーとなるため、ワークスペース直下にフォルダやファイルを作成する方法がわからなかった。

以下のようにするとワークスペース配下にプロジェクトとしてフォルダを作成することはできるが・・・

```java
// ワークスペースにRemoteSystemsTempFilesを作成する
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
IProject project = root.getProject("RemoteSystemsTempFiles");
if (!project.exists()) {
	try {
		project.create(null);
	} catch (CoreException e) {
		e.printStackTrace();
	}
}
```

どうしたらいいのだろうか。