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>
Tagged with: , , , , ,
Posted in Eclipse RCP, Equinox

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).
Tagged with: , , , ,
Posted in Eclipse RCP, Ubuntu

Generating HTML tables with XSLT

The following code snippet is a relatively simple and reusable implementation for generating HTML table content.

    <!-- The number of columns in the generated table -->
    <xsl:variable name="nColumns" select="3" />

    <!--
        XPath indexes start at 1, not 0. 'row' and 'column' template
        parameters therefore default to 1
    -->
    
    <xsl:template name="tableRows">
        <!-- The table content node list -->
        <xsl:param name="items" />
        <!-- The current row index -->
        <xsl:param name="row" select="1" />
        <!--
            Calculate the total number of rows based on the number of
            items and the number of columns
        -->
        <xsl:variable name="nRows" select="ceiling(count($items) div $nColumns)"></xsl:variable>
        <xsl:element name="tr">
            <xsl:call-template name="tableColumns">
                <xsl:with-param name="items" select="$items" />
                <xsl:with-param name="row" select="$row" />
            </xsl:call-template>
        </xsl:element>
         <!--
              There's no loop construct in XSLT so we simply increment
              the row index and call the template again if the current
              row index is less than the total number of rows
         -->
        <xsl:if test="$nRows > $row">
            <xsl:call-template name="tableRows">
                <xsl:with-param name="items" select="$items" />
                <xsl:with-param name="row" select="$row + 1" />
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

    <xsl:template name="tableColumns">
        <!-- The table content node list -->
        <xsl:param name="items" />
        <!-- The current row index -->
        <xsl:param name="row" />
        <!-- The current column index -->
        <xsl:param name="column" select="1" />
        <!--
            Calculate the item index based on the current row and
            column index
        -->
        <xsl:variable name="itemIndex" select="(($row - 1) * $nColumns) + $column" />
        <xsl:element name="td">
            <!-- Check the item index is 'in bounds' -->
            <xsl:if test="count($items) >= $itemIndex">
                <xsl:call-template name="tableCellContent">
                    <xsl:with-param name="item" select="$items[$itemIndex]" />
                </xsl:call-template>
            </xsl:if>
        </xsl:element>
         <!--
              There's no loop construct in XSLT so we simply increment
              the column index and call the template again if the current
              column index is less than the specified number of columns
         -->
        <xsl:if test="$nColumns > $column">
            <xsl:call-template name="tableColumns">
                <xsl:with-param name="items" select="$items" />
                <xsl:with-param name="row" select="$row" />
                <xsl:with-param name="column" select="$column + 1" />
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

    <xsl:template name="tableCellContent">
        <xsl:param name="item" />
        <!-- Generate content for the current item -->
        ...
    </xsl:template>
Tagged with: , , ,
Posted in XSLT

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.

Tagged with: , , , , , , ,
Posted in Eclipse RCP

Installing Squid 3.0 on Fredora 11

  1. Install Squid in the normal fashion using yum or System -> Administration -> Add/Remove Software.
  2. Open the Squid configuration file by executing the following command:
    sudo gedit /etc/squid/squid.conf
  3. Change the value of the error_directory property so that it points to an actual directory. For example:
    error_directory /usr/share/squid/errors/English

    As opposed to

    error_directory /usr/share/squid/errors/en

    which didn’t exist on my system after the install had completed.

  4. If your current SELinux enforcing mode is set to "Enforcing" you’ll also need to perform the following steps.
  5. Create the following Type Enforcement file (the remaining steps assume the file name local.te):
    module local 1.0;
    
    require {
    	type var_run_t;
    	type unconfined_t;
    	type squid_t;
    	class file {open read getattr};
    	class process signal;
    }
    
    #============= squid_t ==============
    allow squid_t var_run_t:file {open read getattr};
    allow squid_t unconfined_t:process signal;

    N.B. The following steps will overwrite any existing module with the same name. To check if you already have a policy module called local go to System -> Administration -> SELinux Management, select "Policy Module" from the left-hand menu and enter "local" into the filter field. If you’ve already got a module called local simply edit the Type Enforcement file accordingly. For example:

    module mysquid 1.0;
  6. Edit accordingly, then execute the following script:
    dir=<your-dir-path>;
    sudo checkmodule -M -m -o $dir/local.mod $dir/local.te;
    sudo semodule_package -o $dir/local.pp -m $dir/local.mod;
    sudo semodule -i $dir/local.pp;

    N.B. The checkmodule command takes the Type Enforcement file, local.te, created in step 5 as its input.

  7. Got to System -> Administration -> Services. Start Squid.
  8. Cleanup any unwanted files created in steps 5 and 6.
Tagged with: , , , ,
Posted in Fedora

Unit Testing HTTPS Clients with a Self-signed Certificate

Overview

A quick and easy way to eliminate javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target without making dangerous changes to your default trust store.

Steps

  1. Create a new keystore and associated key entry by executing the following command (N.B. The password values for the -keypass and -storepass options must be identical for Tomcat to work):
    keytool -genkey -alias tomcat -keyalg RSA -keypass <password> -keystore <user-home>/tomcat.jks -storepass <password>
    
  2. Enter and confirm your details.
  3. Uncomment the “SSL HTTP/1.1 Connector” entry in $CATALINA_BASE/conf/server.xml.
  4. Add keystoreFile and keystorePass attributes with the appropriate values. The result should now resemble the following:
    <!-- Define a SSL HTTP/1.1 Connector on port 8443
    	This connector uses the JSSE configuration, when using APR, the
    	connector should be using the OpenSSL style configuration
    	described in the APR documentation -->
    
    <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
    	maxThreads="150" scheme="https" secure="true"
    	keystoreFile="${user.home}/tomcat.jks" keystorePass="<password>"
    	clientAuth="false" sslProtocol="TLS" />
    
  5. Restart Tomcat and deploy your HTTPS constrained resources.
  6. Add a @BeforeClass method to any tests generating HTTPS requests. Use this method to set the javax.net.ssl.trustStore and javax.net.ssl.trustStorePassword system properties. For example:
    @BeforeClass
    public static void setUp() {
    	System.setProperty("javax.net.ssl.trustStore", "<user-home>/tomcat.jks");
    	System.setProperty("javax.net.ssl.trustStorePassword", "<password>");
    }
    
  7. JSSE now uses the new keystore created in steps 1 and 2 as opposed to the default, <java-home>/jre/lib/security/cacerts, trust store.
Tagged with: , , , , , , ,
Posted in Java EE Development

Scraping Sun Microsystems’ CertManager

Waiting for SCJD or SCEA results can be a bit of a pain. The lucky amongst you may get them in a couple of weeks. On the other hand, you could face a wait of up to six weeks.

To make life a little easier I decided to cobble together an HTML scraper to automate the checking process.

Figure 1. Screenshot

Although there are no binaries at this point in time, you can checkout the source code from SourceForge. For SVN details click the Develop tab.

Usage

According to the CertManager Test History page "tests are imported during regular business hours (GMT -07:00)".

Extending it

Adding your own service listener should be a pretty straightforward task: simply implement PropertyChangeListener and register with the service. As an example; if you live in a timezone other than GMT -07:00, and want to get notified ASAP, you could implement a listener to send an email, or SMS, once the specified test result has been found.

Tagged with: , , , , ,
Posted in Uncategorized
Follow

Get every new post delivered to your Inbox.