views:

10

answers:

1

I need to target both win32.x86 and win32.x86_64 architectures when building an RCP plug-in that uses OS.getRegOpenKey(...). The types of the arguments for the method are different for the two architectures.

I understand now that there is no straightforward way to have an x86 or x86_64 fragment (depending upon the build) override a method in my host plug-in.

However, from this post it sounds like a fragment can, for example, add a class that extends a class in the host. And the host plugin can then explicitly use the ClassLoader to find and instantiate the correct subclass from the fragment included in that architecture's build. What would this look like?

A: 

Based on the linked-to post, this is what I have so far (builds without error now for both architectures, and I just need to see if the built 64-bit app will run on 64-bit Windows!):

Use Eclipse's fragment plug-in wizard to create the x86 and x86_64 fragments. The manifests have a couple of extra lines manually added. For example, the important bits of the x86_64 fragment's Manifest.mf:

...
Bundle-SymbolicName: com.company.product.win32.x86_64;singleton:=true
Fragment-Host: com.company.product.win32;bundle-version="1.0.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Eclipse-PlatformFilter: (& (osgi.os=win32) (osgi.arch=x86_64))
Bundle-ClassPath: src/,. 

Then, added subclass to the fragment (used the same package name as the super class from the host plug-in, but that probably isn't necessary):

package com.company.product.win32;

import org.eclipse.swt.internal.win32.OS;
import org.eclipse.swt.internal.win32.TCHAR;

/**
 * Subclass the host's abstract OSUtilities
 */
public class OSUtilities64 extends OSUtilities {

    public String getRegKeyValue (String path, String key) {
         long [] phkResult = new long [1];
         if (OS.RegOpenKeyEx ((long) OS.HKEY_LOCAL_MACHINE, new TCHAR(0, path, true), 
             0, OS.KEY_READ, phkResult) != 0) {
    ...

Same for the OSUtilities32 class.

Added the fragments to the feature.xml containing the host plug-in:

   <plugin
     id="com.company.product.win32"
     os="win32"
     download-size="0"
     install-size="0"
     version="0.0.0"
     unpack="false"/>
   <plugin
     id="com.company.product.win32.x86"
     os="win32"
     arch="x86"
     download-size="0"
     install-size="0"
     version="0.0.0"
     fragment="true"
     unpack="false"/>
   <plugin
     id="com.company.product.win32.x86_64"
     os="win32"
     arch="x86_64"
     download-size="0"
     install-size="0"
     version="0.0.0"
     fragment="true"
     unpack="false"/>

Then the host plug-in can statically load the appropriate, available class:

/**
 * Get class from appropriate fragment
 */
public static OSUtilities getOSUtilities() {
    ClassLoader loader = OSUtilities.class.getClassLoader();
    try {
        Class<?> cls;
        try {
            cls = loader.loadClass("com.company.product.win32.OSUtilities32");
        } catch (ClassNotFoundException e) {
            cls = loader.loadClass("com.company.product.win32.OSUtilities64");
        }
        OSUtilities util = (OSUtilities) cls.newInstance();
        return util;

I should use the architecture system property to pick which to instantiate -- later.