CowNew
開源團隊網站
www.cownew.com
論壇
http://www.cownew.com/newpeng/?
轉載請保留此信息
有一些插件會自動將需要的jar包自動設置到構建路徑上,比如使用WTP的新建向導新建web項目的時候就會把web開發需要的jar包自動放入項目的構建路徑,使用PDE的“將項目轉換為插件項目”功能后項目的構建路徑中就增加了插件依賴項的庫。我這里來演示一下其實現:
在這個例子中,我們想要做一個“為項目添加lucene支持”的功能,用戶在項目上點擊右鍵,選擇菜單中的“為項目添加lucene支持”以后,插件把lucene的jar包和源碼包拷貝到項目的lib目錄下,并且將jar包加入構建路徑。如下圖:
這是增加lucene支持前的項目結構:
CowNew開源團隊網站www.cownew.com?
?
用戶在項目上點擊右鍵,選擇菜單中的“為項目添加lucene支持”后的項目結構
?
這是工程構建路徑
?
①新建一個插件工程,并將JDT相關的依賴項加入。
②添加一個“org.eclipse.ui.popupMenus”的擴展點,如果不熟悉怎么添加,可以使用插件向導中的“彈出菜單”向導。
需要注意contribution的配置,
此插件只針對Java項目才起作用,因此“objectClass”中填入“org.eclipse.jdt.core.IJavaProject”;
adaptable選擇“true”(后邊講解為什么);
如果是用向導生成的那么請記得清空“nameFilter”。
③下面是核心類ActionAddLucene 的實現代碼
public class ActionAddLucene implements IObjectActionDelegate
{
?private static final String FILESEPARATOR = System.getProperty("file.separator","/");
?private static final String LUCENESRCJAR = "lucene-1.4.3-src.jar";
?private static final String LUCENEJAR = "lucene-1.4.3.jar";
?private static final String LIB = "lib";
?private static final String RESOUCELIB = "resoucelib";
?private IStructuredSelection structSelection;
?public ActionAddLucene()
?{
??super();
?}
?public void setActivePart(IAction action, IWorkbenchPart targetPart)
?{
?}
?public void run(IAction action)
?{
??Object selectObj = structSelection.getFirstElement();
??if (selectObj instanceof IProject)
??{
???IProject project = (IProject) selectObj;
???IJavaProject javaProject = JavaCore.create(project);
???IClasspathEntry[] oldPaths = javaProject.readRawClasspath();
???IClasspathEntry luceneLibEntry = JavaCore.newLibraryEntry(project
?????.getFile(LIB + FILESEPARATOR + LUCENEJAR).getFullPath(), project
?????.getFile(LIB + FILESEPARATOR + LUCENESRCJAR).getFullPath(), null,
?????false);??
???
???if(classPathExists(oldPaths,luceneLibEntry))
???{
????return;
???}
???URL luceneLib = Activator.getDefault().getBundle().getEntry(
?????RESOUCELIB + FILESEPARATOR + LUCENEJAR);
???URL luceneSrc = Activator.getDefault().getBundle().getEntry(
?????RESOUCELIB + FILESEPARATOR + LUCENESRCJAR);
???IClasspathEntry[] newPaths = new IClasspathEntry[oldPaths.length + 1];
???System.arraycopy(oldPaths, 0, newPaths, 0, oldPaths.length);
???IFolder libFolder = project.getFolder(LIB);
???if (!libFolder.exists())
???{
????try
????{
?????libFolder.create(true, true, null);
????} catch (CoreException e)
????{
?????handleException(e);
????}
???}
???copyURLToFile(luceneLib, project, LIB + FILESEPARATOR + LUCENEJAR);
???copyURLToFile(luceneSrc, project, LIB + FILESEPARATOR + LUCENESRCJAR);
???
???newPaths[oldPaths.length] = luceneLibEntry;
???try
???{
????javaProject.setRawClasspath(newPaths, null);
???} catch (JavaModelException e)
???{
????handleException(e);
???}
??}
?}
?private static boolean? classPathExists(IClasspathEntry[] entrys,IClasspathEntry entry)
?{
??for(int i=0,n=entrys.length;i<n;i++)
??{
???if(entrys[i].getPath().equals(entry.getPath()))
???{
????return true;
???}
??}
??return false;
?}
?private static void handleException(Exception e)
?{
??Activator.getDefault().getLog().log(
????new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, e
??????.getMessage(), e));
?}
?private static void copyURLToFile(URL url, IProject project,
???String destFileName)
?{
??InputStream inStream = null;
??try
??{
???inStream = url.openStream();
???IFile file = project.getFile(destFileName);
???if (!file.exists())
???{
????file.create(inStream, true, null);
???}
??} catch (IOException e)
??{
???handleException(e);
??} catch (CoreException e)
??{
???handleException(e);
??} finally
??{
???try
???{
????if (inStream != null)
?????inStream.close();
???} catch (IOException e)
???{
????handleException(e);
???}
??}
?}
?public void selectionChanged(IAction action, ISelection selection)
?{
??structSelection = (IStructuredSelection) selection;
?}
}
下面解釋一下代碼中的重點部分:
①IClasspathEntry[] oldPaths = javaProject.readRawClasspath();
讀取項目原有的構建路徑條目。
②??????
IClasspathEntry luceneLibEntry = JavaCore.newLibraryEntry(project
?????.getFile(LIB + FILESEPARATOR + LUCENEJAR).getFullPath(), project
?????.getFile(LIB + FILESEPARATOR + LUCENESRCJAR).getFullPath(),null,
?????false);??
這一句構建lucene的jar包。
第一個參數是二進制jar包的位置,我們的二進制jar包的位置為項目路徑下的lib/lucene-1.4.3-src.jar;
第二個參數是jar包對應的源碼包的位置;
第三個參數為源碼包的根路徑,lucene的源碼包的源碼根路徑就是jar包的根路徑,因此我們置此參數為null;
第四個參數表示是否導出,我們置為false;
③URL luceneLib = Activator.getDefault().getBundle().getEntry(RESOUCELIB + FILESEPARATOR + LUCENEJAR);
我們把“lucene-1.4.3.jar”、“lucene-1.4.3-src.jar”放到我們插件的“resoucelib”目錄下,當用戶點擊“為項目添加lucene支持”的時候我們要把這兩個文件拷貝到項目的lib目錄下,因此我們需要首先讀取插件路徑“resoucelib”目錄下的這兩個jar包。
讀取插件路徑下的文件我們使用插件Activator類提供的方法即可,比如:
Activator.getDefault().getBundle().getEntry(“config/my.xml”)
就可以讀取到插件根目錄下的文件“config/my.xml”,返回類型是java.net.URL。
④copyURLToFile(luceneLib, project, LIB + FILESEPARATOR + LUCENEJAR);
Activator.getDefault().getBundle().getEntry讀取到的文件位置是URL類型的,我們需要把這個URL對應的文件拷貝到項目的"lib"下。下面看一下copyURLToFile的主干代碼:
?inStream = url.openStream();
?IFile file = project.getFile(destFileName);
?if (!file.exists())
?{
??file.create(inStream, true, null);
?}
URL類有一個openStream可以打開文件的輸入流,IFile也有一個接受輸入流的create方法用來創建文件,因此我們只需要把url的輸入流輸出給IFile的create方法即可。
這里我們也可以由url得到其對應的磁盤上的路徑,也可以得到IFile對應的磁盤上的路徑,然后使用Java IO來進行文件復制操作。但是這樣做不僅代碼數量變多了,而且由于不是使用的Eclipse的資源管理API,會帶來無法自動刷新等問題,因此建議讀者盡量使用Eclipse提供的API來完成功能。