I'm trying to obtain details of an Eclipse user's structured selection in the Navigator Tree view. At present I have the following which is based on the org.eclipse.ui.popMenus extension point:
public void run(IAction action) {
Shell shell = new Shell();
ISelection selection = workbenchPart.getSite().getSelectionProvider().getSelection();
if (structuredSelection instanceof org.eclipse.jface.viewers.TreeSelection) {
org.eclipse.jface.viewers.TreeSelection treeSelection = (org.eclipse.jface.viewers.TreeSelection) structuredSelection;
IAdaptable firstElement = (IAdaptable) treeSelection.getFirstElement();
// Relies on an internal API, bad juju
if (firstElement instanceof org.eclipse.jdt.internal.core.CompilationUnit) {
org.eclipse.jdt.internal.core.CompilationUnit compilationUnit = (org.eclipse.jdt.internal.core.CompilationUnit) firstElement;
String editorSelection = new String(compilationUnit.getContents());
}
}
The problem with this is that it's currently coupled to the JDT compilation unit API, which is internal and too specific for what I want.
Ideally I want to be able to get the underlying file name, type and contents without having to rely on:
This would then allow me to obtain the properties of a generic file when the user right clicks on a file in the navigator view.
Can somebody provide me with any pointers on how I go about doing this please?
[EDIT: I added the following alternative - the original answer is father down]
First: if you select something in the Package Explorer, the selected items are all Java Model objects - you have to deal with them at some level. There are two ways you can handle this:
You can create an adapter factory (which can live in your main plugin or a different one) that eclipse can use to automatically convert from an ICompilationUnit to an IFile.
Note: if you create the adapter factory in a different plugin, you'll probably need to set up an early-startup for it to get the adapter factory loaded. Otherwise, you'll need to have your plugin that will work with the selection depend on the plugin that provides the adapter.
There's some great details on adapters at http://www.eclipse.org/resources/resource.php?id=407, but I'll go over an implementation for this problem here.
The plugin that will host the adapter needs the following dependencies
Define the following class in your new plugin
package com.javadude.foo;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.jdt.core.ICompilationUnit;
public class CompilationUnitToFileAdapter implements IAdapterFactory {
@Override
public Object getAdapter(Object adaptableObject, Class adapterType) {
if (adaptableObject instanceof ICompilationUnit)
// note: "adapting" it here just means returning the ref'd IFile
return (IFile) ((ICompilationUnit)adaptableObject).getResource();
return null;
}
@Override
public Class[] getAdapterList() {
return new Class[] {IFile.class};
}
}
In the plugin that will host the adapter factory, add the following to your plugin.xml:
<extension point="org.eclipse.core.runtime.adapters">
<factory
adaptableType="org.eclipse.jdt.core.ICompilationUnit"
class="com.javadude.foo.AdapterFactory1">
<adapter type="org.eclipse.core.resources.IFile" />
</factory>
</extension>
With the above in place, you can now write:
Object firstElement = ((ITreeSelection) selection).getFirstElement();
IFile file = (IFile) Platform.getAdapterManager().
getAdapter(firstElement, IFile.class);
if (file == null)
// adapter not present; cannot use as IFile
else
// adapter present - you can use it as an IFile
Using this approach, you can add additional adapters to convert other types to IFile and your selection code doesn't care.
[EDIT: I've changing the answer, but leaving the following as reference information b/c it's the standard way to explore the content of a compilation unit that was selected in the package explorer]
This is actually the preferred way to get the contents of a file in the package explorer...
Rather than use CompilationUnit, you should use ICompilationUnit. Most of the eclipse APIs use interfaces for public consumption, and classes for internal details.
If you change your code to
if (firstElement instanceof ICompilationUnit) {
ICompilationUnit unit = (ICompilationUnit firstElement;
String contents = new String(unit.getContents());
}
You'll be in good shape.
To see details of examining/modifying the Java Model and source code:
(In Eclipse)
Help->
Help Contents->
JDT Plug-in Developer's Guide->
Programmer's Guide->
JDT Core
That shows how to work with the Java Model appropriately
To isolate where you reference the java model, you can create an (eclipse) adapter that will convert Java Model objects into files. Assuming such an adapter exists, you can then ask the AdapterManager to convert it to a java file for you. I'll take a peek and see if one exists.
That (decoupling Resource from JDT) was one of the goals of E4 (Eclipse 4).
The plugin list for REsources doesn't mention JDT anymore (again, Eclipse 4.x only):
org.eclipse.core.filesystem
- An abstract, generic file system API, including an implementation of this API for the local file system. This is the API through which the resources plugin accesses an underlying file system.org.eclipse.core.resources
- Contains the API and implementation of the resource modelorg.eclipse.core.resources.compatibility
- A plug-in providing migration support for users opening old workspaces in Eclipse 3.1 or greater A Demo project like e4photo don't require any JDT for accessing IResource from the selection of an IContainer.
void setSelection(@Named(IServiceConstants.ACTIVE_SELECTION)
IResource selection) {
...
IResource[] members = input.members();
...
IResource resource = members[i];
if (resource.getType() == IResource.FILE) {
InputStream contents = ((IFile) resource).getContents();
What are you trying to achieve? Do you want to get file contents? Then you can try:
IAdaptable firstElement = (IAdaptable) treeSelection.getFirstElement();
IFile file = (IFile) firstElement.getAdapter(IFile.class);
if (file != null && file.isAccessible()) {
// Use getContents API
....
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With