<?xml version="1.0" encoding="utf-8" ?> <?eclipse version="3.0"?> <plugin id="org.eclipse.draw2d" name="draw2d" version="3.0.0" provider-name="eclipse.org"> <runtime> <library name="draw2d.jar"> <export name="*" /> <packages prefixes="org.eclipse.draw2d" /> </library> </runtime> <requires> <import plugin="org.eclipse.swt" export="true" /> <import plugin="org.eclipse.core.runtime" /> </requires> </plugin>
  程序員通常會將第二個地方稱為 links 文件夾。這個 links 文件夾中包含 0 個或多個文件,文件名通常都是以 “.link” 擴展名結尾。這些文件中包含了一些鏈接信息,可以使用這些信息定位在磁盤上哪些地方可以找到鏈接插件。
  每個 .link 文件都有一個關鍵字-值對,其格式為 path=location。(例如,links 文件夾 c:/eclipse/links 中就可能會有很多 .link 文件,其中一個文件的名字可能為 com.ibm.indiver.dependencywalker.link。這個文件中唯一的一行可能類似于 path=c:/myplugins/dependencywalker)。這個 .link 文件會將 eclipse 引導到指定的位置,并在 /eclipse/plugins 文件夾中尋找更多的可用插件。
  創建自己的 eclipse 插件依賴性遍歷程序
  編寫一個依賴性遍歷程序基本上分為兩個步驟:首先羅列出所有插件,其次羅列出用戶所選擇的插件的依賴性。
  第一個步驟要負責定位 eclipse 系統中出現的每個插件,并在一個簡單的用戶界面(ui)—— 例如表 —— 中為終端用戶提供所有插件的清單。這個 ui 還應該為用戶提供一些方法來選擇希望解析其依賴性的插件。
  第二個步驟則要對用戶選擇的插件的 plugin.xml 文件進行分析,并查找這個 plugin.xml 文件中嵌入的 <import plugin="plugin id"/> 聲明。這種努力顯然需要對每個插件的 manifest 文件進行遞歸搜索,從而查明依賴插件的整個鏈條。對于描述這個插件可能依賴于其他插件的父-兄-子關系,樹狀視圖是最合適的一種 ui。我們還應該可以直觀地看出某個 eclipse 插件注冊項是否真正加載了一個物理存在的插件。
  步驟 1:羅列 eclipse 系統中的所有插件
  在掌握了以下信息之后,就可以編寫一些代碼來羅列磁盤上物理存在的所有插件了:
  下面是羅列 eclipse 系統中所有插件的詳細步驟:
  清單 2. 準備在 eclipse 系統下物理存在的所有插件的清單
 /**  *    * @return returns a vector containing plugindata objects.  * each plugindata object represents a plugin found under any of the following   * plugin directories  * a. the targetplatformlocation/eclipse/plugins directory,   * b. other plugin directories as specified by *.link files under   *    targetplatform/eclipse/links directory   **/  public static vector getpluginsintargetplatform(){  /**  //step1: get path of target platform.  //step2: prepare path of links folder.  //step3: get list of files in links folder.  //step4: parse each link file and get the path of linked eclipse folder.  //step5: prepare a list of all plugin root folders   //       (eclipse plugins and linked eclipse plugins).  //step6: 6a. for each plugin root folder,   //       6b. go to each plugin directory and get path of plugin.xml.  //step7: parse the plugin.xml file to get plugin id, plugin version,   //       and store in vectors, lists, etc.  //step8: go back to step 6 to continue with next plugin directory.  **/  //step1: get path of target platform.   //fall back to eclipse install location if targetplatform in not set.  url platformurl = platform.getinstalllocation().geturl();  location location = platform.getinstalllocation();  ipath eclipsepath = null ;    //get path of target platform against which the users of this tool   //will compile their code.   ipath targetplatformlocation = new path(gettargetplatformpath(true));  if(_usetargetplatform == false)   eclipsepath = new path(platformurl.getpath());  else   eclipsepath = targetplatformlocation;    showmessage("considering target platform to be: " +      eclipsepath.tostring());    //step2: prepare path of links folder.  //step3: get list of files in links folder.    //step4: parse each link file and get the path of linked eclipse folder.  ipath linkspath = new path( eclipsepath.tostring() ).append("/links");  string linkedpaths[] = getlinkedpaths(linkspath.tostring());  int linkedpathlength = 0;  if(null != linkedpaths){   linkedpathlength = linkedpaths.length;  }    //step5: prepare a list of all plugin root folders   //       (eclipse plugins and linked eclipse plugins).  ipath eclipsepluginrootfolders[] = new ipath[linkedpathlength + 1];  eclipsepluginrootfolders[0] =    new path( eclipsepath.tostring() ).append("/plugins");  if(null != linkedpaths){   for(int i=0; i<linkedpaths.length; i++){    eclipsepluginrootfolders[i+1] =     new path(linkedpaths[i]).append("/eclipse/plugins");   }  }  //step6: 6a. for each plugin root folder,   //       6b. go to each plugin directory and get path of plugin.xml.  //step7: parse the plugin.xml file to get plugin id, plugin version,   //       and store in vectors, lists, etc.  vector vectorsinthisvector = new vector();  for(int i=0; i<eclipsepluginrootfolders.length; i++){   system.out.println("/n========plugin ids and versions in " +    eclipsepluginrootfolders[i] + "========");   vector plugindataobjs  =    getplugindataforallplugins(    eclipsepluginrootfolders[i].tostring());   vectorsinthisvector.add(plugindataobjs);   system.out.println(plugindataobjs);   system.out.println("/n===========|||=== end ===|||===========");  }    vector plugindata = new vector();  iterator outeriterator = vectorsinthisvector.iterator();  while(outeriterator.hasnext()){   vector plugindataobjs = (vector)outeriterator.next();   iterator inneriterator = plugindataobjs.iterator();   while(inneriterator.hasnext()){    plugindata pd = (plugindata)inneriterator.next();    string pluginidkey = pd.getpluginid();    string versionvalue = pd.getpluginversion();    string pluginpath = pd.getpluginlocation();    plugindata.add(pd);   }  }    int breakpoint=0;  return plugindata; } 
  當用戶選擇希望解析依賴鏈的插件之后,我們就需要對用戶所選擇的插件的 plugin.xml 文件進行分析,從而查看它的依賴性。每個依賴性都會導致檢查另外一個 plugin.xml 文件,后者又有自己的依賴性。從用戶選擇的插件開始,這個依賴鏈可以迅速導致有很多個 plugin.xml 文件需要進行分析。我們可以編寫一個遞歸函數來遍歷這些依賴性,它可以查找某個插件的最新版本(針對在相同的系統中有重復插件的情況)以及它的所有依賴性。
  編寫這種遞歸函數需要執行的步驟如下所示,清單 3 給出了這個函數的源代碼。遞歸函數有時對資源的消耗量很大,而且在用戶失去耐心之前可能還沒有返回結果。另外一種選擇是編寫一個函數,只獲取用戶選擇的插件的直接依賴性清單。后一種方法請參看樣例代碼中的 loadimmediatedependencies() 函數。
  清單 3. recursiveplugindependencywalker() 函數
 private vector alreadynotified = new vector(); private boolean firstcall = true; private treeparent root = null; private void recursiveplugindependencywalker(plugindata pdobject,       treeparent parentnode){  try {   string path = pdobject.getpluginlocation();   pluginparser pp = null;   file plugindotxmlfile = new file(path + "/plugin.xml");   if(plugindotxmlfile.exists()){    pp = new pluginparser(plugindotxmlfile);   }else{    file fragmentdotxmlfile = new file(path +      "/fragment.xml");    if(fragmentdotxmlfile.exists()){     pp = new pluginparser(fragmentdotxmlfile);    }else{     return;//no plugin.xml or fragment.xml found    }    }   string displayname = pdobject.getdisplayname();   system.out.println("/nplugin ["+ displayname + "]    requires" + "/n");   string requires[] = pp.getdependencylist();   if(0 != requires.length ){     for(int i=0; i<requires.length; i++){     system.out.println("/t" + requires[i] );     plugindata pd[] =      getplugindataobjectsfrompluginid(requires[i]);     plugindata nextplugin = null;     switch(pd.length){     case 0:      //great, we know there is       //something missing      nextplugin = null;      break;     case 1:      //best case, everything will be smooth      nextplugin = pd[0];      break;     default:      //worst case, there must be more       //than 1 plugin with the same id      //at different locations.      string msgline1 =       "plugin " + displayname +       " requires "  +       requires[i] + "/n";      string msgline2 =       "duplicate plug-ins found for id: /      " " + requires[i] +      "/"" +       "/n continuing with higher version...      " ;            //it is bad to give repeated        //reminders,        //so remind only once per plugin id.      if(! alreadynotified.contains(       new string(requires[i]))){      messagedialog.openinformation(null,      "dependency walker",           msgline1 +         msgline2);      alreadynotified.add(       new string(requires[i]));      }      //always take the better       //version anyway      nextplugin =        getbetterversionplugin(pd);      break;     }//end of switch     if( null != nextplugin ){      treeparent nextinline =       new treeparent(       nextplugin.getdisplayname(),       nextplugin.isplugin       loadedinregistry()       );      parentnode.addchild(nextinline);      recursiveplugindependencywalker(       nextplugin,        nextinline);     }else{      treeparent nextinline =       new treeparent(       requires[i] +        " [this plug-in is missing]       ",       false);      parentnode.addchild(nextinline);      //obviously we can't recurse       //into a missing plugin...     }    }//end of for   }else{    system.out.println("/t nothing:     no further dependency /n" );    //no further dependency   }  } catch (exception e) {   e.printstacktrace();  } }  在這種情況中,必須要確定從這兩個或更多個磁盤副本中選用哪個插件。顯然,我們所感興趣的應該是最新的插件,也就是說,版本較新的插件。我們可以利用現有的一些函數來對 eclipse 插件的版本進行比較,或者可以基于清單 4 所示的樣例代碼編寫一個簡單的函數來對插件版本進行比較。
  清單 4. 比較插件版本
 private plugindata getbetterversionplugin(plugindata pdo[]){  plugindata _pdobjs[] = pdo;  int len = pdo.length;  if(len==0)   return null;    arrays.sort(_pdobjs,new comparator() {   /**compares its two arguments for order.     * returns a negative integer, zero, or a positive integer     * as the first argument is less than, equal to, or greater than     * the second.     **/   public int compare(object leftobj, object riteobj) {        string leftpid = ((plugindata)leftobj).     getpluginversion().replace('.', ':');    string ritepid = ((plugindata)riteobj).     getpluginversion().replace('.', ':');    string leftid[] = leftpid.split(":");    string riteid[] = ritepid.split(":");    int maxlen = leftid.length > riteid.length ?       leftid.length : riteid.length;    for(int i=0; i<maxlen; i++){     int left = 0;     int rite = 0;     try {     left = new integer(leftid[i]).intvalue();     } catch (nullpointerexception e) { left = 0; }     try {     rite = new integer(riteid[i]).intvalue();     } catch (nullpointerexception e) { rite = 0; }          if(left==rite){      continue;     }else{     int bigger = left > rite ? left : rite;      if(bigger==left)       return 1;      if(bigger==rite)       return -1;     }         }    return 0;   }   public boolean equals(object arg0) {    return false;   }  });    return _pdobjs[len-1];   } 
新聞熱點
疑難解答