This tutorial describes how to use the Eclipse resource API.
1. Eclipse Resources API for manipulating files
The Eclipse resource API allows you to access, create, delete and update resources like projects, folders and files. It also allows you to register for resource changes.
1.1. Resource API
For example, you can create and open a project via the following code.
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRoot root = workspace.getRoot();
IProject project = root.getProject("performancetest");
try {
project.create(new NullProgressMonitor());
project.open(new NullProgressMonitor());
} catch (CoreException e) {
ILog.get().error("Could not create project", e);
}
1.2. Resource change notification
You can register for resource changes via an IResourceChangeListener, which you add via IWorkspace.addResourceChangeListener.
Listeners are informed which resources changed and how they changed.
The update is proportional to the size of the change and not the size of the workspace.
The object passed to a resource change listener is an instance of IResourceChangeEvent.
It contains:
-
the event type, an integer that describes what event occurred, for example,
POST_CHANGE -
the modification (added, removed, or changed)
-
the precise nature of the change (the change flags)
-
a summary of the markers that changed on the resource
-
deltas for any added, removed, or changed children
The tree of deltas is structured like the tree of workspace IResource objects.
Each delta object corresponds to exactly one resource.
The top-most delta object, provided by the event object, corresponds to the IWorkspaceRoot resource returned by IWorkspace.getRoot.
The resource delta hierarchy includes deltas for all affected resources that existed prior to the resource changing operation, and all affected resources that existed after the operation.
Think of it as the union of the workspace contents before and after a particular operation, with all unchanged sub-trees pruned out.
Change notifications may not be immediate, as resource change operations may be nested into other operations.
For example, calling IFile.move uses IFile.create to create the new file, and then IFile.delete to remove the old file.
Since the creation and deletion operations are nested inside the move operation, there is only one notification.
If your code performs batch changes, wrap them into an ICoreRunnable and pass it to IWorkspace.run.
Wrapping high-level operations inside an ICoreRunnable can lead to a substantial performance improvement, because it ensures that only one resource change broadcast occurs, instead of potentially thousands.
|
A |
2. Exercise: Create project with lots of files
Use a plug-in called com.vogella.resources for this exercise.
If you already created it in another exercise, reuse it, otherwise create it.
2.1. Add dependency
Add dependencies to your plug-in, so that its MANIFEST.MF file looks similar to the following listing.
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Resources
Bundle-SymbolicName: com.vogella.resources;singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: VOGELLA
Automatic-Module-Name: com.vogella.resources
Bundle-RequiredExecutionEnvironment: JavaSE-25
Require-Bundle: org.eclipse.jface,
org.eclipse.core.runtime,
org.eclipse.core.resources,
org.eclipse.ui.workbench,
org.eclipse.ui.ide,
org.eclipse.ui,
org.eclipse.e4.ui.model.workbench,
org.eclipse.e4.core.di,
org.eclipse.e4.ui.services,
org.eclipse.core.filesystem,
org.eclipse.e4.ui.workbench,
org.eclipse.e4.core.services
Import-Package: jakarta.inject;version="[2.0.0,3.0.0)"
2.2. Add handler
Contribute a command and a handler named CreateLargeProjectHandler in the com.vogella.resources.handlers package via the commands.e4xmi model fragment of this plug-in.
Add a menu entry for this command to the vogella menu, which has the com.vogella.tasks.ui.menu.vogella ID.
The handler creates a new project with lots of files and opens an editor for each of them.
Ensure that the commands.e4xmi file and the icons folder are listed in the bin.includes of your build.properties file, otherwise the contribution is missing at runtime.
package com.vogella.resources.handlers;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.ILog;
import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.ide.IDE;
public class CreateLargeProjectHandler {
private final Random random = new Random();
private static final String CHARSFORCREATION = "abcdefghijklmnopqrstuvwxyz";
@Execute
public void execute(IWorkbenchPage page) {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IProject project = workspace.getRoot().getProject("performancetest");
List<IFile> files = new ArrayList<>();
try {
// batch all resource changes into a single resource change event
workspace.run(monitor -> {
if (!project.exists()) {
project.create(monitor);
}
project.open(monitor);
for (int i = 0; i < 30; i++) {
IFolder folder = project.getFolder("test" + i);
if (!folder.exists()) {
folder.create(true, true, monitor);
}
for (int j = 0; j < 30; j++) {
IFile file = folder.getFile(createString(10));
file.create(createBytes(5000), IResource.NONE, monitor);
files.add(file);
}
}
}, null);
} catch (CoreException e) {
ILog.get().error("Could not create the test project", e);
return;
}
for (IFile file : files) {
try {
IDE.openEditor(page, file);
} catch (PartInitException e) {
ILog.get().error("Could not open an editor for " + file.getName(), e);
}
}
}
private byte[] createBytes(int length) {
byte[] bytes = new byte[length];
random.nextBytes(bytes);
return bytes;
}
private String createString(int length) {
StringBuilder buf = new StringBuilder(length);
// fill the string with random characters up to the desired length
for (int i = 0; i < length; i++) {
buf.append(CHARSFORCREATION.charAt(random.nextInt(CHARSFORCREATION.length())));
}
return buf.toString();
}
}
|
Such code can, for example, be useful for a test setup.
The code passes an |
2.3. Verify
Start your runtime Eclipse and validate that you can create a new project with your handler.
3. Exercise: Close all editors for files in your workspace
Write a new CloseAllEditorsHandler handler in the com.vogella.resources.handlers package, which closes all editors that show a file from your workspace.
Contribute it with a command named Close Workspace Editors and a menu entry in the vogella menu, as in the previous exercise.
You can use the following example code for that.
package com.vogella.resources.handlers;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
public class CloseAllEditorsHandler {
@Execute
public void execute(IWorkbenchPage page) {
List<IEditorReference> editorsToClose = new ArrayList<>();
for (IEditorReference editorReference : page.getEditorReferences()) {
try {
// only close editors which show a file from the workspace
if (editorReference.getEditorInput().getAdapter(IFile.class) != null) {
editorsToClose.add(editorReference);
}
} catch (PartInitException e) {
// the editor input cannot be restored, so the editor does not show a workspace file
}
}
page.closeEditors(editorsToClose.toArray(IEditorReference[]::new), true);
}
}
4. Additional information Eclipse Resources API
4.1. vogella Java example code
If you need more assistance we offer Online Training and Onsite training as well as consulting