Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Eclipse Plug-in Development FAQ"

(Work with native code)
(How do I make a title area dialogue with radio buttons?)
(15 intermediate revisions by 6 users not shown)
Line 24: Line 24:
 
Are you getting errors like "Unhandled loop event exception" messages in your console with nothing useful after it? Make sure you have [http://wiki.eclipse.org/Graphical_Eclipse_FAQs#I_get_an_unhandled_event_loop_exception_in_my_console._What_gives.3F -consoleLog] as a '''Program Argument''' in your launch configuration. You may also want to take a look at these [[Core Tools|runtime tools]].
 
Are you getting errors like "Unhandled loop event exception" messages in your console with nothing useful after it? Make sure you have [http://wiki.eclipse.org/Graphical_Eclipse_FAQs#I_get_an_unhandled_event_loop_exception_in_my_console._What_gives.3F -consoleLog] as a '''Program Argument''' in your launch configuration. You may also want to take a look at these [[Core Tools|runtime tools]].
  
===I'm using third party jar files and my plug-in is not working...===
+
===I'm using third party jar files and my plug-in is not working===
 
Did you add those jars to your project's '''Java Build Path'''? Do not use that project property page when developing plug-ins. You have two options.
 
Did you add those jars to your project's '''Java Build Path'''? Do not use that project property page when developing plug-ins. You have two options.
  
Line 41: Line 41:
 
# Export any packages that you need to using the PDE Editor>Runtime tab
 
# Export any packages that you need to using the PDE Editor>Runtime tab
 
# Save
 
# Save
 +
 +
'''Common mistakes for option 2'''
 +
 +
One common mistake is to forget to add the '.' to the classpath after adding your library.
 +
If you fail to do this, your plug-in will crash with a message like this:
 +
        java.lang.ClassNotFoundException: lib.foo.Bar
 +
        at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:513)
 +
        at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:429)
 +
        at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:417)
 +
        at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
 +
        at java.lang.ClassLoader.loadClass(Unknown Source)
 +
        ...
 +
 +
Example of META-INF/MANIFEST.MF:
 +
        // lib.foo MANIFEST.MF
 +
        Manifest-Version: 1.0
 +
        Bundle-ManifestVersion: 2
 +
        Bundle-Name: Foo
 +
        Bundle-SymbolicName: lib.foo;singleton:=true
 +
        Bundle-Version: 1.0.0.qualifier
 +
        Bundle-Activator: lib.foo.Activator
 +
        Bundle-ActivationPolicy: lazy
 +
        Bundle-RequiredExecutionEnvironment: JavaSE-1.6
 +
        Import-Package: org.osgi.framework;version="1.6.0"
 +
        Export-Package: lib.foo
 +
        Bundle-ClassPath: lib/someRandomDep.jar  <--- WRONG
 +
        Bundle-ClassPath: .,lib/someRandomDep.jar  <--- CORRECT
 +
 +
Also check whether your build.properties file now lists the '.' and the 'lib'-directory (or whatever you named it) in 'bin.includes':
 +
        bin.includes = META-INF/,\
 +
              lib/,\
 +
              .
 +
             
 +
  
 
Check out {{bug|108781}}.
 
Check out {{bug|108781}}.
Line 91: Line 125:
  
 
===A plug-in in my 'Eclipse Application' launch configuration is listed as being "out of sync", what should I do?===
 
===A plug-in in my 'Eclipse Application' launch configuration is listed as being "out of sync", what should I do?===
One known workaround to this problem is to remove your workspace's <code>.metadata/org.eclipse.pde.core</code> folder. Cleaning and reloading the target platform does not appear to fix this problem.
+
Open the Problems View, click on the small downwards triangle in the views menu and select 'Group by'=Type. Look through the Plugin Problems, fixing anything which has to do with the "Out Of Sync" Plugin.
 +
 +
Another known workaround to this problem is to remove your workspace's <code>.metadata/org.eclipse.pde.core</code> folder. Cleaning and reloading the target platform does not appear to fix this problem.
  
===Work with native code===
+
===How do I include native libraries in my bundle?===
When you want to use Native libraries within your plug-in using custom libraries, you can either tell the user to set the appropriate System environment path, or include those libraries in the plug-in. This can be done the following way:
+
When you want to use native libraries within your bundle using custom libraries, you can either tell the user to set the appropriate system environment path or include those libraries in the plug-in.
Edit your MANIFEST.MF manually by adding the following lines
+
 
 +
If you wish to include the natives in your bundle, continue reading.
 +
 
 +
Edit your <tt>MANIFEST.MF</tt> manually by adding the following lines
 
<source lang="ini">
 
<source lang="ini">
 
Bundle-NativeCode:  
 
Bundle-NativeCode:  
  /libs/occjava-mingw/yourlib.dll;  
+
  /libs/yourlib.dll;  
  /libs/occ-mingw/someotherlib.dll;  
+
  /libs/someotherlib.dll;  
 
  osname=win32; processor=x86
 
  osname=win32; processor=x86
 
</source>
 
</source>
( Also check out: http://litrik.blogspot.com/2007/08/secrets-of-bundle-nativecode.html )
+
 
Afterwards, explicitly load all libraries manually using System.loadLibrary();
+
(Also see [http://litrik.blogspot.com/2007/08/secrets-of-bundle-nativecode.html here])
 +
 
 +
Afterwards, explicitly load all libraries manually using <tt>System.loadLibrary()</tt>.
 +
 
 
<source lang="java">
 
<source lang="java">
 
ArrayList<String> list = new ArrayList<String>();
 
ArrayList<String> list = new ArrayList<String>();
Line 112: Line 154:
 
}
 
}
 
</source>
 
</source>
Be careful: You get an UnsatisfiedLinkError when you load a library which depends on a library which hasn't been loaded yet. To overcome this automatically, you can iterate over a list of the required libraries, and throw all out which could be loaded, until the list is empty. Like this, you can compute the correct ordering for loading your libraries.
+
 
 +
'''Caution:''' If you get an <tt>UnsatisfiedLinkError</tt> when you load a library which depends on a library which hasn't been loaded yet. To overcome this automatically, you can iterate over a list of the required libraries, and throw all out which could be loaded, until the list is empty. Like this, you can compute the correct ordering for loading your libraries.
  
 
<source lang="java">
 
<source lang="java">
Line 145: Line 188:
 
}
 
}
 
</source>
 
</source>
Please note, that for debugging e.getMessage() may give you more information for debugging. It helped me in cases where I misspelled some libraries.
+
 
You shouldn't use this code for production but to compute the correct ordering of your libraries!
+
Please note that for debugging, <tt>e.getMessage()</tt> may give you more information for debugging. It can assist you if you mistyped some of the library names for instance.
 +
 
 +
You should not use this code for production but to compute the correct ordering of your libraries!
  
 
==User Interface==
 
==User Interface==
Line 291: Line 336:
  
 
===How do I make a New / Import / Export Wizard appear in the context menu of the Project Explorer?===
 
===How do I make a New / Import / Export Wizard appear in the context menu of the Project Explorer?===
Add an extension to the extension point [http://help.eclipse.org/helios/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/extension-points/org_eclipse_ui_navigator_navigatorContent.html org.eclipse.ui.navigator.navigatorContent] with a commonWizard element that points to the ID of your wizard.  
+
Add an extension to the extension point [http://help.eclipse.org/helios/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/extension-points/org_eclipse_ui_navigator_navigatorContent.html org.eclipse.ui.navigator.navigatorContent] with a commonWizard element that points to the ID of your wizard.
 +
 
 +
===How do I show a message dialogue for exceptions and log them? ===
 +
Often when catching exceptions, it's puzzling as to what one is suppose to do with them.
 +
 
 +
The following code solves this dilemma. It is reccomended to put this into your activator.
 +
 
 +
It produces a message box as such:
 +
 
 +
[[File:OpenErrorPerfPlugin.png]]
 +
 
 +
The details show the stack trace.
 +
 
 +
It then logs the caught exception in the error-logging framework.
 +
 
 +
To use the code, call it as following:
 +
 
 +
<source lang="java">
 +
        try {
 +
            throw new EmptyStackException();
 +
        }
 +
        catch (EmptyStackException ex) {
 +
            openError(ex, "End of the world is near");
 +
        }
 +
 
 +
//      ....
 +
 
 +
    /**
 +
    * Log the given exception and display the message/reason in an error
 +
    * message box. (From org.eclipse.linuxtools.packagekit.ui.Activator)
 +
    *
 +
    * @param ex the given exception to display
 +
    * @since 2.0
 +
    */
 +
    public void openError(Exception ex, final String title) {
 +
        StringWriter writer = new StringWriter();
 +
        ex.printStackTrace(new PrintWriter(writer));
 +
 
 +
        final String message = ex.getMessage();
 +
        final String formattedMessage = PLUGIN_ID + " : " + message; //$NON-NLS-1$
 +
        final Status status = new Status(IStatus.ERROR, PLUGIN_ID, formattedMessage, new Throwable(writer.toString()));
 +
 
 +
        getLog().log(status);
 +
        Display.getDefault().asyncExec(new Runnable() {
 +
            @Override
 +
            public void run() {
 +
                ErrorDialog.openError(Display.getDefault().getActiveShell(),
 +
                        title, message, status);
 +
            }
 +
        });
 +
    }
 +
 
 +
</source>
 +
(It gets the default instance and calls the method).
 +
 
 +
(It is safe to call this from any thread, as this opens the dialogue from the U.I thread)
 +
 
 +
An example of this can be found in: (note, this is internal, avoid referencing. Instead copy the code into your plugin.)
 +
<source lang="java">
 +
org.eclipse.linuxtools.internal.perf.PerfPlugin.openError(Exception, String)
 +
</source>
 +
 
 +
=== How do I launch a dialogue from a non-ui thread and get a return value ===
 +
In a U.I thread, you typically have access to a shell.
 +
In a background process, you usually don't and if you try to get it you get an exception.
 +
 
 +
The way around this is to create a runnable object and make the UI thread run it.
 +
Also, you use 'syncExec' (as oppose to asyncExec), which forces the current code to wait until the runnable has completed execution.
 +
 
 +
Example source code:
 +
<source lang="java">
 +
 
 +
        //define some final variable outside the runnable. This should have a getter/setter method.
 +
        final AtomicBoolean userChoice = new AtomicBoolean(false);
 +
 
 +
        //To generate U.I, we make sure to call the U.I thread,
 +
        //otherwise we get an U.I exception.
 +
        PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
 +
            @Override
 +
            public void run() {
 +
 
 +
                Shell parent = PlatformUI.getWorkbench().getDisplay().getActiveShell();  //get shell.
 +
                boolean okPressed = MessageDialog.openConfirm(parent, "prof err",
 +
                        "Flag is not set in options. Would you like to add/rebuild?");
 +
 
 +
                if (okPressed) {
 +
                    userChoice.set(true);
 +
                } else
 +
                    userChoice.set(false);
 +
                }
 +
        });
 +
 
 +
        //Retrieve the value that the runnable changed.
 +
        return userChoice.get();
 +
</source>
 +
 
 +
 
 +
=== How do I make a title area dialogue with radio buttons? ===
 +
An example of how you can extend the title area dialogue to suit your needs is shown in [[https://wiki.eclipse.org/Eclipse_Plug-in_Development_FAQ/TitleAreaDialogWithRadioButtons title area dialogue with radio buttons]]
  
 
==Editors==
 
==Editors==
Line 469: Line 612:
  
 
==Release==
 
==Release==
===How do I make a p2 repository===
+
===How do I make a p2 repository?===
  
 
This is not the only way to create a repository, and it may not be the best way, but it worked for me. YMMV.
 
This is not the only way to create a repository, and it may not be the best way, but it worked for me. YMMV.
Line 513: Line 656:
 
</project>
 
</project>
 
</source>
 
</source>
 +
 +
===How do I add files to the root of the installation directory?===
 +
You can include [http://help.eclipse.org/indigo/index.jsp?topic=/org.eclipse.pde.doc.user/tasks/pde_rootfiles.htm] with your build.
 +
 +
PDE/Build will take the feature root files and generate p2 artifacts with touchpoint stuff to do the right thing at install time.
  
 
[[Category:FAQ]]
 
[[Category:FAQ]]
 
[[Category:RCP]]
 
[[Category:RCP]]

Revision as of 11:33, 20 June 2014

This page is a collection of FAQs that is intended to help a developer write Eclipse plug-ins.

This FAQ is intended to be complimentary to the Official Eclipse FAQ and RCP FAQ wiki pages. If you cannot find your question here, you should try checking those other two pages.

Contents

General Development

How do I find a class from Eclipse?

See here.

I see these $NON-NLS-1$ tags all over the place when I'm browsing Eclipse's source code? What do they mean?

They are meant to mark a string literal as not needing to be externalized (as in, translated / localized). You will often see something like...

if (string.equals("")) { //$NON-NLS-1$
    // do stuff
}

...this would be a scenario where a string wouldn't need to be localized because it is a string for the code to "manipulate", per se, over it being part of a message to the user at the UI level.

I need help debugging my plug-in...

Are you getting errors like "Unhandled loop event exception" messages in your console with nothing useful after it? Make sure you have -consoleLog as a Program Argument in your launch configuration. You may also want to take a look at these runtime tools.

I'm using third party jar files and my plug-in is not working

Did you add those jars to your project's Java Build Path? Do not use that project property page when developing plug-ins. You have two options.

Option 1: turn the jars into plug-ins Use New > Project > Plug-in Development > Plug-in from existing JAR archive. That will turn one or more jar files into a single jar plug-in. For something like log4j you can then set up Buddy-Classloading, etc.

Prior to 3.2.1, you had to make modifications to the build.properties file. See bug 146042 (RCP export has problems with required plug-ins).

Option 2: include the jars in a plug-in

  1. Use Import>File System to import the jar files into your plug-in project, say in the <project>/lib directory.
  2. Use "Add..." to add the jars to the classpath section of the PDE Editor>Runtime tab.
  3. Use "New..." to add "." library back (with no quotes, of course). Some versions of eclipse automatically do this for you.
  4. Make sure your binary build exports the new jar files on the PDE Editor>Build tab.
  5. Save
  6. On the project, use the popup menu>PDE Tools>Update Classpath to correctly add the jars to the eclipse project classpath.
  7. Export any packages that you need to using the PDE Editor>Runtime tab
  8. Save

Common mistakes for option 2

One common mistake is to forget to add the '.' to the classpath after adding your library. If you fail to do this, your plug-in will crash with a message like this:

       java.lang.ClassNotFoundException: lib.foo.Bar
       at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:513)
       at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:429)
       at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:417)
       at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
       at java.lang.ClassLoader.loadClass(Unknown Source)
       ...

Example of META-INF/MANIFEST.MF:

       // lib.foo MANIFEST.MF
       Manifest-Version: 1.0
       Bundle-ManifestVersion: 2
       Bundle-Name: Foo
       Bundle-SymbolicName: lib.foo;singleton:=true
       Bundle-Version: 1.0.0.qualifier
       Bundle-Activator: lib.foo.Activator
       Bundle-ActivationPolicy: lazy
       Bundle-RequiredExecutionEnvironment: JavaSE-1.6
       Import-Package: org.osgi.framework;version="1.6.0"
       Export-Package: lib.foo
       Bundle-ClassPath: lib/someRandomDep.jar  <--- WRONG
       Bundle-ClassPath: .,lib/someRandomDep.jar  <--- CORRECT

Also check whether your build.properties file now lists the '.' and the 'lib'-directory (or whatever you named it) in 'bin.includes':

       bin.includes = META-INF/,\
              lib/,\
              .
              


Check out bug 108781.

It talks about how adding a 3rd party jar removes the default "." classpath, and the need to add it back.

Also, Eclipse can handle jars within jars. It expands them into a temporary location during runtime.

What is the IAdaptable interface?

The articles below may be of your interest.

How do I read from a file that I've included in my bundle/plug-in?

The FileLocator class should be able to do most of the things that you want. It can open up a java.io.InputStream as well as provide a java.io.File. You should keep in mind that the java.io.File approach is not going to work if your bundle is packaged as a jar file. To get a reference to your bundle's Bundle instance, you can use Platform's getBundle(String) method. Alternatively, if your bundle's activator subclasses Plugin or AbstractUIPlugin, then you can just call getBundle() from it directly. If your activator simply implements the BundleActivator interface, then from your implementation of the start(BundleContext) method, you can just call getBundle() on the passed in BundleContext to store the Bundle instance in a field for retrieval later. You can also query for Bundle instances from the PackageAdmin service.

// your BundleActivator implementation will probably look something
// like the following
public class Activator implements BundleActivator {
  private static Activator instance;
 
  private Bundle bundle;
 
  public void start(BundleContext context) throws Exception {
    instance = this;
    bundle = context.getBundle();
  }
 
  public void stop(BundleContext context) throws Exception {
    instance = null;
  }
 
  public static Activator getDefault() {
    return instance;
  }
 
  public Bundle getBundle() {
    return bundle;
  }
}
 
// code to retrieve an java.io.InputStream
InputStream inputStream = FileLocator.openStream(
    Activator.getDefault().getBundle(), new Path("resources/setup.xml"), false);

Where do I find the javadoc for the Eclipse API locally? I don't always want to load stuff up in a browser.

You will already have the javadocs for the Eclipse Platform if you installed the Eclipse SDK. The HTML files are stored in the org.eclipse.platform.doc.isv jar file located in your eclipse/plugins folder. Likewise, you can find JDT APIs in their org.eclipse.jdt.doc.isv jar file and so on.

A plug-in in my 'Eclipse Application' launch configuration is listed as being "out of sync", what should I do?

Open the Problems View, click on the small downwards triangle in the views menu and select 'Group by'=Type. Look through the Plugin Problems, fixing anything which has to do with the "Out Of Sync" Plugin.

Another known workaround to this problem is to remove your workspace's .metadata/org.eclipse.pde.core folder. Cleaning and reloading the target platform does not appear to fix this problem.

How do I include native libraries in my bundle?

When you want to use native libraries within your bundle using custom libraries, you can either tell the user to set the appropriate system environment path or include those libraries in the plug-in.

If you wish to include the natives in your bundle, continue reading.

Edit your MANIFEST.MF manually by adding the following lines

Bundle-NativeCode: 
 /libs/yourlib.dll; 
 /libs/someotherlib.dll; 
 osname=win32; processor=x86

(Also see here)

Afterwards, explicitly load all libraries manually using System.loadLibrary().

ArrayList<String> list = new ArrayList<String>();
list.add("yourlib");
list.add("someotherlib");
for (String lib : list) {
	System.loadLibrary(lib);
}

Caution: If you get an UnsatisfiedLinkError when you load a library which depends on a library which hasn't been loaded yet. To overcome this automatically, you can iterate over a list of the required libraries, and throw all out which could be loaded, until the list is empty. Like this, you can compute the correct ordering for loading your libraries.

/**
 * Iterate through the list of libraries and remove all libraries from the list
 * that could be loaded. Repeat this step until all libraries are loaded.
 * The Reason: You can only load a library, if all dependent libraries have
 * already been loaded. So you need to know the correct ordering from the
 * leafs to the root. Load the leafs first!
 */
ArrayList<String> toRemove;
int i = 10; //cancel after 10 iterations. You probably forgot to mention a library to load.
while (!list.isEmpty() && (i > 0)) {
	toRemove = new ArrayList<String>();
	int j = 0;
	while (j < list.size() - 1) {
		try {
			System.loadLibrary(list.get(j));
			toRemove.add(list.get(j));
			System.out.println("loaded library " + j + ": " + list.get(j));
		} catch (Throwable e) {
//					System.out.println(e.getMessage());
//					System.out.println("error loading lib: " + list.get(j));
		}
		j++;
	}
	for (String lib : toRemove) {
		//System.out.println("removing lib : " + lib);
		list.remove(lib);
	}
	i--;
}

Please note that for debugging, e.getMessage() may give you more information for debugging. It can assist you if you mistyped some of the library names for instance.

You should not use this code for production but to compute the correct ordering of your libraries!

User Interface

There's a view / editor that I want to model. How do I find out what its source looks like and how it was designed?

Views and editors generally extend ViewPart and EditorPart respectively. Placing a breakpoint in its constructor when you show the view or editor or invoking the "Plug-in Spy" with the Alt+Shift+F1 keybinding will tell you what the name of that class is. From there, you can inspect the class's code to see how it works. In the case of the user interface elements, you should look at its implementation of the createPartControl(Composite) method.

If you cannot get "Plug-in Spy" to run, you may not have PDE installed.

There's a preference / property page that I want to model. How do I find out what its source looks like and how it was designed?

Put a breakpoint in the constructors of the PreferencePage / PropertyPage class. Open the preferences / properties dialog, and then select the page you are interested about. Now you can identify which class is constructing that page based on the stack trace.

You can also invoke the "Plug-in Spy" with the Alt+Shift+F1 keybinding to retrieve information about the page that your mouse is currently hovering over. If you cannot get "Plug-in Spy" to run, you may not have PDE installed.

There's a window / dialog / popup that I want to model. How do I find out what its source looks like and how it was designed?

There are two usual suspects, an SWT Shell or a JFace Window. Generally, most developers subclass's JFace's Dialog class (which is a subclass of Window) for their dialog needs. So you should first try and put a breakpoint in Window's open() method and see if the window you're trying to model stops at that breakpoint when it has been opened (shown). If not, try Shell's open() or setVisible(boolean) methods.

You can also invoke the "Plug-in Spy" with the Alt+Shift+F1 keybinding to retrieve information about the window that your mouse is currently hovering over. If you cannot get "Plug-in Spy" to run, you may not have PDE installed.

Wayne's blog post may be of help to you.

There's a wizard page that I want to model. How do I find out what its source looks like and how it was designed?

Wizard pages usually extend the WizardPage class. Putting a breakpoint in its constructor will help you identify the class that is creating that page.

You can also invoke the "Plug-in Spy" with the Alt+Shift+F1 keybinding to retrieve information about the wizard that your mouse is currently hovering over. If you cannot get "Plug-in Spy" to run, you may not have PDE installed.

How can I leverage the 'Outline' view?

In your IWorkbenchPart's implementation, you should override the getAdapter(Class) method and return your own implementation of IContentOutlinePage or you can choose to subclass ContentOutlinePage.

public Object getAdapter(Class adapter) {
    if (adapter.equals(IContentOutlinePage.class)) {
        return page;
    }
    // do NOT forget this line
    return super.getAdapter(adapter);
}

How can I show the perspective bar in my RCP application?

In your concrete subclass of WorkbenchWindowAdvsior, you should override its preWindowOpen() method and then call setShowPerspectiveBar(boolean) on your IWorkbenchWindowConfigurer (which you retrieve by invoking getWindowConfigurer()).

How do I get the perspective bar to show on the top right corner?

The code below will demonstrate this.

PlatformUI.getPreferenceStore().setValue(IWorkbenchPreferenceConstants.DOCK_PERSPECTIVE_BAR, IWorkbenchPreferenceConstants.TOP_RIGHT);

How do I warn the user that a workbench part that is not currently visible has changed?

From your WorkbenchPart subclass, you can use the code below. Please note that the code below currently only works on views. For notification support in editors, please see bug 86221.

IWorkbenchSiteProgressService service = (IWorkbenchSiteProgressService) part.getSite().getService(IWorkbenchSiteProgressService.class);
// notify the user by turning the workbench part's title bold
service.warnOfContentChange();

How can I make use of the workbench's browser capabilities?

To leverage the workbench's browser capabilities, you will have to interact with the IWorkbenchBrowserSupport class. The code below will show you how to retrieve an implementation of this interface and open a website with the external browser:

try {
    IWorkbenchBrowserSupport browserSupport = PlatformUI.getWorkbench().getBrowserSupport();
    browserSupport.getExternalBrowser().openURL(new URL("http://www.eclipse.org"));
} catch (PartInitException e) {
    // handle the exception
}

How do I retrieve the id of a preference page?

You can try the following code below:

public String getId(IPreferencePage page) {
    PreferenceManager pm = PlatformUI.getWorkbench().getPreferenceManager();
    List list = pm.getElements(PreferenceManager.PRE_ORDER);
 
    for (int i = 0; i < list.size(); i++) {
        PreferenceNode node = (PreferenceNode) list.get(i);
        IPreferencePage p = node.getPage();
 
        if (p == page) {
            return node.getId();
        }
    }
    return null;
}

How do I ask my decorator to decorate items?

You can try the following code below:

PlatformUI.getWorkbench().getDecoratorManager().update("com.mycompany.product.ui.decoratorId");

How do I get the icon associated with a file or content type?

You can try the following code below:

IContentType contentType = IDE.getContentType(file);
ImageDescriptor imageDescriptor =
    PlatformUI.getWorkbench().getEditorRegistry().getImageDescriptor(file.getName(), contentType);

How do I set the selection of an editor or view?

You can retrieve the selection provider from a workbench part from its site.

IWorkbenchPartSite site = workbenchPart.getSite();
ISelectionProvider provider = site.getSelectionProvider();
// this can be null if the workbench part hasn't set one, better safe than sorry
if (provider != null) {
    provider.setSelection(...);
}

How do I get the selection of an editor or view?

You can retrieve the selection from the ISelectionService or get it directly from the selection provider of the part from its site.

ISelectionService selectionService = (ISelectionService) serviceLocator.get(ISelectionService.class);
ISelection selection = selectionService.getSelection(partId);
/* ... */


IWorkbenchPartSite site = workbenchPart.getSite();
ISelectionProvider provider = site.getSelectionProvider();
// this can be null if the workbench part hasn't set one, better safe than sorry
if (provider != null) {
    ISelection selection = provider.getSelection();
    /* ... */
}

How do I get progress feedback in the status bar in my RCP application?

Try adding the following piece of code in your WorkbenchWindowAdvisor's preWindow() implementation:

public void preWindowOpen() {
    getWindowConfigurer().setShowProgressIndicator(true);
}

How do I make a New / Import / Export Wizard appear in the context menu of the Project Explorer?

Add an extension to the extension point org.eclipse.ui.navigator.navigatorContent with a commonWizard element that points to the ID of your wizard.

How do I show a message dialogue for exceptions and log them?

Often when catching exceptions, it's puzzling as to what one is suppose to do with them.

The following code solves this dilemma. It is reccomended to put this into your activator.

It produces a message box as such:

OpenErrorPerfPlugin.png

The details show the stack trace.

It then logs the caught exception in the error-logging framework.

To use the code, call it as following:

         try {
            throw new EmptyStackException();
        }
        catch (EmptyStackException ex) {
            openError(ex, "End of the world is near");
        }
 
//       ....
 
     /**
     * Log the given exception and display the message/reason in an error
     * message box. (From org.eclipse.linuxtools.packagekit.ui.Activator)
     *
     * @param ex the given exception to display
     * @since 2.0
     */
    public void openError(Exception ex, final String title) {
        StringWriter writer = new StringWriter();
        ex.printStackTrace(new PrintWriter(writer));
 
        final String message = ex.getMessage();
        final String formattedMessage = PLUGIN_ID + " : " + message; //$NON-NLS-1$
        final Status status = new Status(IStatus.ERROR, PLUGIN_ID, formattedMessage, new Throwable(writer.toString()));
 
        getLog().log(status);
        Display.getDefault().asyncExec(new Runnable() {
            @Override
            public void run() {
                ErrorDialog.openError(Display.getDefault().getActiveShell(),
                        title, message, status);
            }
        });
    }

(It gets the default instance and calls the method).

(It is safe to call this from any thread, as this opens the dialogue from the U.I thread)

An example of this can be found in: (note, this is internal, avoid referencing. Instead copy the code into your plugin.)

org.eclipse.linuxtools.internal.perf.PerfPlugin.openError(Exception, String)

How do I launch a dialogue from a non-ui thread and get a return value

In a U.I thread, you typically have access to a shell. In a background process, you usually don't and if you try to get it you get an exception.

The way around this is to create a runnable object and make the UI thread run it. Also, you use 'syncExec' (as oppose to asyncExec), which forces the current code to wait until the runnable has completed execution.

Example source code:

        //define some final variable outside the runnable. This should have a getter/setter method. 
        final AtomicBoolean userChoice = new AtomicBoolean(false);
 
        //To generate U.I, we make sure to call the U.I thread,
        //otherwise we get an U.I exception.
        PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
            @Override
            public void run() {
 
                Shell parent = PlatformUI.getWorkbench().getDisplay().getActiveShell();  //get shell. 
                boolean okPressed = MessageDialog.openConfirm(parent, "prof err",
                        "Flag is not set in options. Would you like to add/rebuild?");
 
                if (okPressed) {
                    userChoice.set(true);
                } else
                    userChoice.set(false);
                }
        });
 
        //Retrieve the value that the runnable changed. 
        return userChoice.get();


How do I make a title area dialogue with radio buttons?

An example of how you can extend the title area dialogue to suit your needs is shown in [title area dialogue with radio buttons]

Editors

How do I add those rectangles in my source editor like what JDT does for parameter names during code completion?

To achieve this, you will need to use a LinkedModeModel and a LinkedModeUI. Open the 'Call Hierarchy' on either of the two constructors to find out how to use those two classes.

How do I implement a 'Quick Outline' for my editor?

JDT's implementing class is named 'org.eclipse.jdt.internal.ui.text.JavaOutlineInformationControl', you should take a look at that.

How do I get an editor's StyledText widget?

Since you cannot access the editor's ITextViewer, you will have to try using the code below.

StyledText text = (StyledText) editor.getAdapter(Control.class);

How can I get the IDocument from an editor?

Assuming the editor adapts to the ITextEditor interface, you can try the code below.

ITextEditor editor = (ITextEditor) editorPart.getAdapter(ITextEditor.class):
if (editor != null) {
  IDocumentProvider provider = editor.getDocumentProvider();
  IDocument document = provider.getDocument(editor.getEditorInput());
}

This code should work on most text editors.

How do I get an IFile given an IEditorPart or IEditorInput?

The code below will demonstrate how to do this.

IFile file = (IFile) editorPart.getEditorInput().getAdapter(IFile.class);
if (file != null) {
    // do stuff
}

Note that IFiles are meant to represent files within the workspace and will not work if the file that has been opened is not contained within the workspace. Instead, a FileStoreEditorInput is usually passed into the editor when the editor is opening a file outside the workspace.

How do I hide the tabs of a MultiPageEditorPart if it only has one page?

Adding the code below into your MultiPageEditorPart's subclass should do the trick.

protected void createPages() {
    super.createPages();
    if (getPageCount() == 1) {
        Composite container = getContainer();
        if (container instanceof CTabFolder) {
            ((CTabFolder) container).setTabHeight(0);
        }
    }
}

How do I change the editor that is being opened when a marker has been opened?

You can associate the string ID of your editor onto your marker with IMarker's setAttribute(String, Object) method by using the EDITOR_ID_ATTR string constant defined in the IDE class as the attribute name.

marker.setAttribute(IDE.EDITOR_ID_ATTR, "com.example.xyz.editorID");

How can I make my editor respond to a user opening a marker?

When a marker has been opened, the Eclipse Platform tries to help the user out via the IGotoMarker interface. Your editor should either implement the interface or respond to this class by returning an implementation via the getAdapter(Class) method.

public Object getAdapter(Class adapter) {
    if (adapter.equals(IGotoMarker.class)) {
        return gotoMarker;
    }
    return super.getAdapter(adapter);
}

IGotoMarker's gotoMarker(IMarker) method will be called accordingly on the corresponding interface implementation and it is in that method implementation that you can react to a user opening a marker.

Why does the workbench keep opening a new editor every time I open a marker?

Are you using a custom IEditorInput implementation for your editor? You should override Object's equals(Object) method to return true if your custom implementation is equal to another IEditorInput.

Clients implementing this editor input interface should override Object.equals(Object) to answer true for two inputs that are the same. The IWorbenchPage.openEditor APIs are dependent on this to find an editor with the same input.

How should I let my editor know that its syntax colours have changed?

You should return true when you receive the proper notifications through AbstractTextEditor's affectsTextPresentation(PropertyChangeEvent) method.

How do I close one/all of my editors upon workbench shutdown so that it won't appear upon workbench restart?

See here.

How do I prevent a particular editor from being restored on the next workbench startup?

In your IEditorInput implementation, you can return null for getPersistable() or false for exists().

Debug

How do I invoke a process and have its output managed by the 'Console' view?

Use DebugPlugin's newProcess(ILaunch, Process, String) or newProcess(ILaunch, Process, String, Map) method. You will probably be calling this in your ILaunchConfigurationDelegate implementation.

How do I associate my executed process with its command line counterpart?

Your IProcess implementation must return a valid string that corresponds to the IProcess.ATTR_CMDLINE attribute. The sample code below will demonstrate how this is done with the DebugPlugin's newProcess(ILaunch, Process, String, Map) method.

String commandLine = "/usr/bin/make";
Map attributes = new HashMap();
attributes.put(IProcess.ATTR_CMDLINE, commandLine);
Process process = Runtime.getRuntime().exec(commandLine);
// this assumes that 'launch' is a non-null reference to an ILaunch implementation
DebugPlugin.newProcess(launch, process, "make", attributes);

How do I capture the output of my launched application like the 'Console' view?

If the underlying IProcess allows for the retrieval of its IStreamsProxy, you can retrieve a corresponding IStreamMonitor and attach an IStreamListener onto it to monitor changes to the stream.

The sample code below will demonstrate how to read the InputStream of an executed process:

String commandLine = "/usr/bin/make";
Process process = Runtime.getRuntime().exec(commandLine);
IProcess iProcess = DebugPlugin.newProcess(launch, process, "make", attributes);
iProcess.getStreamsProxy().getOutputStreamMonitor().addListener(new IStreamListener(){
    public void streamAppended (String text, IStreamMonitor monitor){
       //TODO: As per user requirement. 
    }
});

How do I run Eclipse launch configurations programmatically?

Let us say you want to contribute to the PackageExplorer and run a CompilationUnit using a context menu. This is how you would run a Java Application using a dynamic launch configuration.

First, an ILaunchConfiguration is created by using its ILaunchConfigurationType. Already existing types can be obtained via the ILaunchManager:

ILaunchConfigurationType javaType = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurationType(IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION);
ILaunchConfigurationWorkingCopy config = javaType.newInstance(null, name);

Then you need so set each attribute to complete your launch configuration. Check out JavaRuntime for further methods, e.g. variable entries.

List<String> classpath = new ArrayList<String>();
classpath.add(JavaRuntime.newArchiveRuntimeClasspathEntry(new Path("/project.web/src/main/java")).getMemento());
classpath.add(JavaRuntime.newArchiveRuntimeClasspathEntry(new Path("/lib/dev-2.0.0.jar")).getMemento());
classpath.add(JavaRuntime.newRuntimeContainerClasspathEntry(new Path( JavaRuntime.JRE_CONTAINER ), IRuntimeClasspathEntry.STANDARD_CLASSES, project).getMemento());
classpath.add(new DefaultProjectClasspathEntry(project).getMemento());
config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_CLASSPATH, classpath);
 
config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_CLASSPATH, false);
 
List<String> resourceTypes = new ArrayList<String>();
List<String> resourcePaths = new ArrayList<String>();
resourcePaths.add("/project.web");
resourceTypes.add("4");
config.setAttribute(LaunchConfiguration.ATTR_MAPPED_RESOURCE_TYPES, resourceTypes);
config.setAttribute(LaunchConfiguration.ATTR_MAPPED_RESOURCE_PATHS, resourcePaths);
 
config.setAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, true);
 
config.setAttribute(JavaMainTab.ATTR_CONSIDER_INHERITED_MAIN, true);
config.setAttribute(JavaMainTab.ATTR_INCLUDE_EXTERNAL_JARS, true);
 
config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, "project.Main");
config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, "-startupUrl index.html");
config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, "project.web");
config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, "-Xmx256M");

Now you can either run it directly in Eclipse...

DebugUITools.launch(config, ILaunchManager.RUN_MODE);

...or save this configuration, which is great for verifying the attributes.

config.doSave();

See also FAQ How do I launch a Java program?

Release

How do I make a p2 repository?

This is not the only way to create a repository, and it may not be the best way, but it worked for me. YMMV.

  • Initially, create a project in your workspace called "UpdateSite".
    • If you choose a different name, some of the following steps will need modification.
  • Export the updated plugins and features:
    • Select the features you want to release in the Package Explorer view.
    • Choose File -> Export from the menu.
    • Plug-In Development -> Deployable Features, click Next
    • Select features to update
    • Destination Directory should be the UpdateSite project in your workspace.
    • Turn off "generate repository metadata"
    • Click Finish
  • Edit your category.xml and add any new or updated features to it, in the correct categories.
  • Generate the artifacts.xml file using the ant build.xml file below with target="artifacts"
  • Generate the content.jar with categories:
  • Launch an eclipse application with the following parameters:
    • -application org.eclipse.equinox.p2.publisher.CategoryPublisher
    • -consolelog
    • -repositoryName "My Update Site"
    • -metadataRepository file:${project_loc:UpdateSite}
    • -categoryDefinition file:${project_loc:UpdateSite}/category.xml
    • -categoryQualifier
    • -compress

Here is the Ant build file for generating artifacts.xml

<?xml version="1.0" encoding="UTF-8"?>
<project name="project" default="artifacts">
  <target name="artifacts">
    <delete file="artifacts.xml"/>
    <delete file="content.xml"/>
    <delete file="artifacts.jar"/>
    <delete file="content.jar"/>
    <p2.publish.featuresAndBundles 
      repository="file:${basedir}" 
      repositoryname="My Update Site"
      source="${basedir}" 
      compress="true" />
  </target>
</project>

How do I add files to the root of the installation directory?

You can include [1] with your build.

PDE/Build will take the feature root files and generate p2 artifacts with touchpoint stuff to do the right thing at install time.

Back to the top