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
  1. tree.addSelectionListener(new SelectionListener(){
  2. @Override
  3. public void widgetSelected(SelectionEvent e) {
  4. // TODO Auto-generated method stub
  5. Tree element = (Tree) e.getSource();
  6. TreeItem[] t = element.getSelection();
  7. if(t != null && t.length > 0 && treeMap.containsKey(t[0].getText())){
  8. Bundle bundle = Platform.getBundle("com.bin.practice.prefs");
  9. try {
  10. Class clazz = bundle.loadClass("com.bin.practice.dialog.MessageDialogTest");
  11. Constructor constr[] = clazz.getConstructors();
  12. Object object = constr[0].newInstance(formBody.getShell(), t[0].getText());
  13. Method method = clazz.getMethod("open");
  14. method.invoke(object);
  15. } catch (Exception e1) {
  16. // TODO Auto-generated catch block
  17. TitleAreaDialogTest dialog = new TitleAreaDialogTest(formBody.getShell(), t[0].getText());
  18. dialog.open();
  19. }
  20. }
  21. }
  22. @Override
  23. public void widgetDefaultSelected(SelectionEvent e) {
  24. // TODO Auto-generated method stub
  25. }
  26. });

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

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

MessageDialogTest.java
  1. public class MessageDialogTest extends Dialog {
  2. private String item;
  3. public MessageDialogTest(Shell parent, String item) {
  4. super(parent);
  5. // TODO Auto-generated constructor stub
  6. this.item = item;
  7. }
  8. protected Control createDialogArea(Composite parent) {
  9. Composite container = (Composite) super.createDialogArea(parent);
  10. GridLayout layout = new GridLayout(1, false);
  11. container.setLayout(layout);
  12. GridData grid = new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1);
  13. grid.widthHint = 200;
  14. grid.heightHint = 200;
  15. Label label = new Label(container, SWT.NONE);
  16. label.setText("Select item is "+this.item);
  17. label.setLayoutData(grid);
  18. return container;
  19. }
  20. @Override
  21. protected void configureShell(Shell newShell) {
  22. super.configureShell(newShell);
  23. newShell.setText("MessageDialogTest");
  24. }
  25. @Override
  26. protected Point getInitialSize() {
  27. return new Point(450, 300);
  28. }
  29. }

TitleAreaDialogTest.java
  1. public class TitleAreaDialogTest extends TitleAreaDialog{
  2. private String item;
  3. public TitleAreaDialogTest(Shell parentShell, String item) {
  4. super(parentShell);
  5. // TODO Auto-generated constructor stub
  6. this.item = item;
  7. }
  8. @Override
  9. protected Control createDialogArea(Composite parent) {
  10. setTitle("TitleAreaDialogTest");
  11. setMessage("Please confrim yout selection!");
  12. Composite composite = new Composite(parent, SWT.NONE);
  13. GridLayout layout = new GridLayout(1, false);
  14. composite.setLayout(layout);
  15. GridData grid = new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1);
  16. grid.widthHint = 200;
  17. grid.heightHint = 200;
  18. Label label = new Label(composite, SWT.NONE);
  19. label.setText("Select item is "+this.item);
  20. label.setLayoutData(grid);
  21. return composite;
  22. }
  23. }

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

MessageDialogTest視窗


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

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


留言