Eclipse Plug-in - Load other bundle's class dynamically

這篇主要是探討如何動態載入其他bundle plugin內的class,不會因為在run的時候沒有勾選相

關的plugin而導致出錯的情形! 當您的程式內有引用到其他bundle的class時,您必須先在該

bundle內將該class所在的package在plugin.xml內做export動作,之後在自己bundle的plugin.xml

內做import package的動作,如此一來才能夠順利在該程式做import。

但是,假設今天對於要引用的bundle是採用可有可無的狀態,也就是說假設在我們run的時

候,不勾選該plugin如此一來我們就不能用export、import package的方式,否則程式會出錯!


因為Eclipse採用OSGi framework來串起各個plugin之間的關係,如此一來在編譯的時候雖然

沒有出錯,但執行時期卻出錯了,將導致該相關的功能出問題!

因此我們會想說利用Java Reflection來達到這個目的,在run時候有勾選的的話一樣會出錯

表示ClassNotFundException


若在run的時候沒勾選相關plugin的話會出現NullPointerException



因此,找到這篇作者有提到關於 buddy class loading in Eclipse

在欲引用的plugin的plugin.xml頁面內的MANIFEST.MF頁籤內增加

Eclipse-BuddyPolicy: registered

在本身的plugin的plugin.xml頁面內的MANIFEST.MF頁籤內增加

Eclipse-RegisterBuddy: reference plugin id(自行填入)

如此一來,該程式即可正確引入該class

建立的相關範例說明如下:

將從這篇文章內的範例進行修改

Eclipse Plug-in - Implement TreeViewer for autoExpand and autoPack functions

劇情為我們點擊treeviewer內的子項目後,將彈出一個dialog

首先本身的plugin及另一個plugin分別如下

com.bin.practice.ui (本身)
com.bin.practice.prefs (另一個)

在treeviewer部分,我們增加了SelectionListener
tree.addSelectionListener(new SelectionListener(){

   @Override
   public void widgetSelected(SelectionEvent e) {
    // TODO Auto-generated method stub
    Tree element = (Tree) e.getSource();
    TreeItem[] t = element.getSelection();
    if(t != null && t.length > 0 && treeMap.containsKey(t[0].getText())){
     Bundle bundle = Platform.getBundle("com.bin.practice.prefs");
     try {
      Class clazz = bundle.loadClass("com.bin.practice.dialog.MessageDialogTest");
      Constructor constr[] = clazz.getConstructors();
      Object object = constr[0].newInstance(formBody.getShell(), t[0].getText());
      Method method = clazz.getMethod("open");
      method.invoke(object);
      
     } catch (Exception e1) {
      // TODO Auto-generated catch block
      TitleAreaDialogTest dialog = new TitleAreaDialogTest(formBody.getShell(), t[0].getText());
      dialog.open();
     }
    }
   }

   @Override
   public void widgetDefaultSelected(SelectionEvent e) {
    // TODO Auto-generated method stub
   }
  });

由於treeviewer內有分成父節點與子節點,因此會利用treeMap(存放子節點)來判斷是否為

子節點,若是的話則彈出dialog。

MessageDialogTest.java
public class MessageDialogTest extends Dialog {
 private String item;
 
 public MessageDialogTest(Shell parent, String item) {
     super(parent);
     // TODO Auto-generated constructor stub
     this.item = item;
 }
 
 
 protected Control createDialogArea(Composite parent) {
     Composite container = (Composite) super.createDialogArea(parent);
  
     GridLayout layout = new GridLayout(1, false);
     container.setLayout(layout);
  
     GridData grid = new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1);
     grid.widthHint = 200;
     grid.heightHint = 200;
      
     Label label = new Label(container, SWT.NONE);
     label.setText("Select item is "+this.item);
     label.setLayoutData(grid);
  
     return container;
 }
 
 @Override
    protected void configureShell(Shell newShell) {
  super.configureShell(newShell);
        newShell.setText("MessageDialogTest");
    }
 
 @Override
    protected Point getInitialSize() {
        return new Point(450, 300);
    }
}

TitleAreaDialogTest.java
public class TitleAreaDialogTest extends TitleAreaDialog{
 private String item;
 
 public TitleAreaDialogTest(Shell parentShell, String item) {
    super(parentShell);
    // TODO Auto-generated constructor stub
    this.item = item;
 }
 
 @Override
 protected Control createDialogArea(Composite parent) {
    setTitle("TitleAreaDialogTest");
    setMessage("Please confrim yout selection!");
        
    Composite composite = new Composite(parent, SWT.NONE);
        
    GridLayout layout = new GridLayout(1, false);
    composite.setLayout(layout);
  
    GridData grid = new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1);
    grid.widthHint = 200;
    grid.heightHint = 200;
      
    Label label = new Label(composite, SWT.NONE);
    label.setText("Select item is "+this.item);
    label.setLayoutData(grid);
  
    return composite;
 }
}

而假設在執行的時候有勾選com.bin.practice.prefs的話,則程式將繼續執行,打開

MessageDialogTest視窗


執行的結果,在click該項目後

若是不勾選該項目的話,則重新執行後點擊彈出的視窗為


留言