Setting up a Local p2 Repository

I’m currently working on an Eclipse RCP application that uses PAX Logging. The easiest way to use the required bundles is to put them in a folder referenced by your Target Platform Definition. However, there are a couple of major drawbacks to this approach:

  1. Tycho requires p2 metadata in order to resolve dependencies, so the local folder approach won’t work if you’re using Tycho for a headless build
  2. Log4j Import-Package failures. Every time I started Eclipse I had to reset my target platform because Import-Package: org.apache.log4j;version="1.2.15";provider=paxlogging was failing

Based on the Equinox documentation I created the following ant build file to publish a local p2 repository. The only prerequisite is that all the required PAX Logging bundles are placed in a folder, relative to the build file, called lib/plugins (see p2-build.xml in-line comments). Once you’ve created your repository you can use your favourite web server to make it available to Tycho.

p2-build.xml

<?xml version="1.0" encoding="UTF-8"?>
<project name="local-p2" default="create-p2" basedir=".">

    <!-- 3rd party bundles should be placed in
         a subdirectory called 'plugins' -->
    <property name="source.dir" location="${basedir}/lib" />
    <!-- the directory the repository will be
         created in -->
    <property name="repo.dir" value="${basedir}/repository" />

    <target name="clean">
        <delete dir="${repo.dir}" />
        <mkdir dir="${repo.dir}" />
    </target>

    <target name="create-p2" depends="clean">
        
        <makeurl file="${repo.dir}" property="repo.url" />
        <echo message="Repository URL: ${repo.url}"/>
        <makeurl file="${basedir}/category.xml" property="category.file.url" />

        <!-- Use a fileset include to avoid hard-coding
             the equinox launcher jar filename -->
        <pathconvert property="launcher.jar">
            <fileset dir="${eclipse.home}/plugins/">
                <include name="org.eclipse.equinox.launcher_*.jar" />
            </fileset>
        </pathconvert>
        <echo message="Using Equinox launcher: ${launcher.jar}"/>

        <!-- Assumes 3rd party bundles are located in
             ${source.dir}/plugins -->
        <p2.publish.featuresAndBundles
            repository="${repo.url}"
            publishArtifacts="true"
            compress="false"
            source="${source.dir}" />

        <!-- See category.xml -->
        <exec executable="java">
            <arg value="-jar" />
            <arg value="${launcher.jar}" />
            <arg value="-console" />
            <arg value="-consolelog" />
            <arg value="-application" />
            <arg value="org.eclipse.equinox.p2.publisher.CategoryPublisher" />
            <arg value="-metadataRepository" />
            <arg value="${repo.url}" />
            <arg value="-categoryDefinition" />
            <arg value="${category.file.url}" />
            <arg value="-categoryQualifier" />
        </exec>
    </target>

</project>

category.xml

<?xml version="1.0" encoding="UTF-8"?>
<site>
    <bundle id="org.ops4j.pax.configmanager" version="0.2.2">
        <category name="ops4j" />
    </bundle>
   <bundle id="org.ops4j.pax.logging.pax-logging-api" version="1.7.3">
      <category name="ops4j"/>
   </bundle>
   <bundle id="org.ops4j.pax.logging.pax-logging-service" version="1.7.3">
      <category name="ops4j"/>
   </bundle>
   <category-def name="ops4j" label="ops4j"/>
</site>
Advertisements

Ubuntu Virtual Machine Setup

To successfully build an e4 RCP application for Mac OX S you need a Linux environment. The following instructions are a record of how I set up Ubuntu 14.04 on VirtualBox 4.3.12

Prerequisites

  • Windows 7 Professional 64-bit
  • VirtualBox 4.3.12
  • ubuntu-14.04.1-desktop-amd64.iso

Creating an Ubuntu VM on VirtualBox

  1. Open ‘Oracle VM VirtualBox Manager’ and create a new virtual machine with the following attributes:
    • Type: Linux
    • Version: Ubuntu (64bit)
    • RAM: 2048 MB
    • Hard drive: VDI, Dynamically Allocated, 10 GB
  2. Start the new VM and select ubuntu-14.04.1-desktop-amd64.iso as the installation image
  3. Follow the onscreen instructions to install Ubuntu
  4. Shutdown the VM and set the following display properties in the video tab:
    • Video Memory: 128 MB
    • Enable 3D Acceleration: selected
  5. Start Ubuntu and run the following command:
    sudo apt-get install virtualbox-guest-dkms virtualbox-guest-utils virtualbox-guest-x11

    (see Screen Resolution Problem with Ubuntu 14.04 and VirtualBox for more information on why this is required)

  6. Restart the VM

Dev Environment Setup

JDK 1.8

  1. To install JDK 1.8 run the following commands:
    sudo add-apt-repository ppa:webupd8team/java
    sudo apt-get update
    sudo apt-get install oracle-java8-installer

Eclipse for RCP and RAP Developers

  1. Download the latest Linux 64-bit version of ‘Eclipse for RCP and RAP Developers’ (currently Luna RC3) and extract it to a suitable location
  2. Create an eclipse.desktop file by running the following command:
    sudo -H gedit /usr/share/applications/eclipse.desktop

    Add the following content, replacing ‘path-to-eclipse-executable’ with the appropriate value:

    [Desktop Entry] 
    Type=Application 
    Name=Eclipse 
    Icon=eclipse 
    Exec=env UBUNTU_MENUPROXY= path-to-eclipse-executable 
    Terminal=false 
    Categories=Development;IDE;Java;
  3. Install e4 Tools
    1. Go to the eclipse e4 project downloads page
    2. Select the latest release (currently 1.6)
    3. Copy the ‘online p2 repo link’ URL
    4. Start eclipse and create a new ‘software update site’ using the URL from the previous step
    5. Install the ‘Eclipse 4 – Core Tools’ feature
  4. Install EGit via the ‘Help – Eclipse Marketplace’ menu item

Git

  1. Run the following command to install Git:
    sudo apt-get install git

    (see Getting Started – Installing Git for more information)

  2. For a graphical front end, download and install SmartGit

Additional Ubuntu Configuration

Shared Folder(s)

  1. Create a new folder on the Windows host
  2. Open ‘Oracle VM VirtualBox Manager’, select ‘Settings – Shared Folders’ and click the ‘Add’ button
  3. Select the newly created folder by selecting ‘Other’ from the ‘Folder Path’ dropdown list
  4. Check the ‘Auto-mount’ and ‘Make Permanent’ options and click ‘OK’
  5. Run the following command in Ubuntu, replacing ‘your-user-name’ with the appropriate value:
    sudo adduser your-user-name vboxsf
  6. Restart Ubuntu and confirm the folder is accessible by running:
    ls /media/

Auto-hide the Launcher

  1. Select ‘System Settings – Appearance – Behaviour’ to auto-hide the launcher
  2. If the launcher doesn’t reappear when you move the mouse to the designated area simply press ALT+F1 or the Windows key to toggle launcher visibility

Changing the Default Search Categories and Sources

  1. Select ‘System Settings – Security & Privacy – Search’ to exclude online search results
  2. Install dconf Editor by running the following command:
    sudo apt-get install dconf-tool
  3. Open dconf Editor and select ‘com – canonical – unity – lenses’
  4. Add/remove any required/unwanted scopes (see How to get the list of Dash search plugins (scopes) in command line? for more information).

Eclipse 4.4.0 – Tool bar item visibility based on the currently active perspective

Displaying trimmed window tool bar items based on the currently active perspective in an Eclipse 4.4.0 RCP application would seem like a straightforward task but it actually involves a fair bit of tinkering and there are a few not so obvious pitfalls along the way.

After reading section 31.2 of Lars Vogel’s Eclipse 4 RCP tutorial the obvious approach was to associate a ‘visible-when’ expression with each of my perspective-specific tool bar items. The first problem I encountered was the fact that expressions are not evaluated for items added directly to the main tool bar (see Bug 400217). By ‘added directly’ I mean added as children of the tool bar element in the e4xmi application model. Luckily, when added as ToolBar Contributions visible-when expressions are evaluated as expected.

The next problem I encountered was how to determine the currently active perspective from within a visible-when expression. I couldn’t find any up to date documentation regarding the names of predefined context variables and none of the variables listed in Command Core Expressions were available in my Eclipse Luna 4.4.0 RCP application. To determine which context variables were available I added the following @CanExecute method to one of my tool bar item command handlers:

@CanExecute
public boolean canExecute(final IEclipseContext ictx) {
    final EclipseContext ctx = (EclipseContext) ictx.getParent();
    System.out.println("### START ###");
    for (final Entry<String, Object> entry : ctx.localData().entrySet()) {
        System.out.println(String.format("Key: '%s', value: '%s'", entry.getKey(), entry.getValue()));
    }
    System.out.println("### END ###");
    return true;
}

The following entry was included in the output from this method:

 Key: 'org.eclipse.e4.ui.model.application.ui.advanced.MPerspective', value: 'org.eclipse.e4.ui.model.application.ui.advanced.impl.PerspectiveImpl@2d778add (elementId: my.example.perspective.Edit, tags: [], contributorURI: platform:/plugin/my.example.application) (widget: Composite {}, renderer: org.eclipse.e4.ui.workbench.renderers.swt.PerspectiveRenderer@7fc44dec, toBeRendered: true, onTop: false, visible: true, containerData: null, accessibilityPhrase: null) (label: Edit, iconURI: null, tooltip: , context: PerspectiveImpl (my.example.perspective.Edit) Context, variables: [])'

Based on this output I wrote the following following Property Tester to query the elementId of the active perspective:

/**
 * Property tester that checks the <code>elementId</code> of the currently active perspective
 */
public class PerspectivePropertyTester extends PropertyTester {

    /**
     * @param receiver the currently active {@link MPerspective}
     * @param property the property to test, in this case 'elementId'
     * @param args additional arguments, in this case an empty array
     * @param expectedValue the expected value of {@link MPerspective#getElementId()}
     */
    @Override
    public boolean test(final Object receiver, final String property, final Object[] args, final Object expectedValue) {
        final MPerspective perspective = (MPerspective) receiver;
        return perspective.getElementId().equals(expectedValue);
    }
}

This was then configured in plugin.xml as follows:

<?xml version="1.0" encoding="UTF-8"?>
<plugin>
   ...
   <extension point="org.eclipse.core.expressions.propertyTesters">
      <propertyTester class="my.example.application.propertytester.PerspectivePropertyTester"
            id="my.example.application.propertytester.PerspectivePropertyTester"
            namespace="my.example.property"
            properties="perspectiveId"
            type="org.eclipse.e4.ui.model.application.ui.advanced.MPerspective">
      </propertyTester>
   </extension>
   <extension point="org.eclipse.core.expressions.definitions">
      <definition id="my.example.expression.isEditPerspective">
         <with variable="org.eclipse.e4.ui.model.application.ui.advanced.MPerspective">
            <test forcePluginActivation="true"
                  property="my.example.property.perspectiveId"
                  value="my.example.perspective.Edit">
            </test>
         </with>
      </definition>
      <definition id="my.example.expression.isPreviewPerspective">
         <with variable="org.eclipse.e4.ui.model.application.ui.advanced.MPerspective">
            <test forcePluginActivation="true"
                  property="my.example.property.perspectiveId"
                  value="my.example.perspective.Preview">
            </test>
         </with>
      </definition>
   </extension>
   ...
</plugin>

As a footnote I should also note that subscribing to UIEvents.UILifeCycle.PERSPECTIVE_OPENED events does not work as expected (see Bug 408681) so the above approach is probably the best option. You could, of course, set the visibility of tool bar items programmatically when switching perspective but this is far from ideal.