Java項目模型
Eclipse的項目有很多種包括Java項目C++項目C#項目等每種項目都有自己的特點我們最常接觸到的項目就是Java項目因此我們重點來講解一下Java項目模型
Java模型是用來對與創建編輯和構建Java程序相關聯的對象進行建模的一些類Java模型類是在re中定義的這些類實現資源的特定於Java的行為並進一步將Java資源分解成模型元素
Java模型的繼承結構圖如圖所示
圖 Java模型的繼承結構圖
IJavaElement的子類接口還有IMethodIType等在這裡沒有全部列出Java模型中的類結構比較簡單級次也非常少
下面介紹一下各個接口的主要方法
() IJavaElement
exists判斷元素是否存在處理Java元素與處理資源對象相似當使用Java元素時實際上是在使用某些底層的模型對象的句柄必須使用exists()來確定元素是否真正存在於工作空間中
getElementName返回元素的名稱
getJavaModel返回其對應的JavaModel返回值類型是IJavaModel
getJavaProject返回元素對應的Java工程返回值類型是IJavaProject
getParent返回父元素返回值類型是IJavaElement
getResource返回元素對應的資源返回值類型是IResource
() IClassFile
此接口代表編譯後的class二進制文件
isClass判斷是否是Java類
isInterface判斷是否是接口
() ICompilationUnit
此接口代表Java源文件
getAllTypes返回此文件中定義的所有類型返回值類型是IType[]一個Java文件中可以定義多個類型
getPrimary返回主類型返回值類型是ICompilationUnit
() IJavaModel
此接口表示根 Java 元素對應於工作空間是所有具有 Java 性質的項目的父類它對於Java項目的作用和IWorkspaceRoot對於IProject的作用相似
contains判斷是否存在指定的資源
getJavaProject返回指定名字的Java項目返回值類型是IJavaProject
getJavaProjects返回所有的Java項目返回值類型是IJavaProject[]
getWorkspace返回所在的工作空間
() IJavaProject
此接口表示Java項目
IJavaElement findElement(IPath path)返回項目的path路徑下的Java元素
IPackageFragment findPackageFragment(IPath path)返回項目的path路徑下的IPackageFragment
IPackageFragmentRoot findPackageFragmentRoot(IPath path)返回項目的path路徑下的IPackageFragmentRoot
findType根據一個全名取得此元素的類型此類有數個重載方法返回值類型為IType
getAllPackageFragmentRoots返回所有的IPackageFragmentRoot返回值類型是IPackageFragmentRoot[]
getOutputLocation返回輸出路徑返回值類型是IPath
getRequiredProjectNames返回依賴項目返回值類型是字符串數組
setOutputLocation設定輸出路徑
() IPackageFragment
此接口表示整個包或者包的一部分
createCompilationUnit創建一個ICompilationUnit返回值類型是ICompilationUnit
getClassFile返回指定名稱對應的IClassFile返回值類型是IClassFile
getClassFiles返回所有的IClassFile返回值類型是IClassFile[]
getCompilationUnit返回指定名稱對應的ICompilationUnit返回值類型是ICompilationUnit
getCompilationUnits返回所有ICompilationUnit返回值類型是ICompilationUnit[]
getKind判斷此包是源碼包還是普通包返回值是int型如等於IPackage FragmentRootK_SOURCE則是源文件包如等於IPackageFragmentRootK_BINARY則為普通包
hasSubpackages是否有子包
() IPackageFragmentRoot
此接口表示一組包段並將各段映射至底層資源它可以是文件夾JAR或ZIP文件
createPackageFragment創建一個IPackageFragment返回值類型是IPackage Fragment
getKind此包段是源碼包段還是二進制包段返回值類型是int如果等於IPackageFragmentRootK_SOURCE則是源文件包段如果等於IPackageFragment RootK_BINARY則為二進制包段
getPackageFragment根據包名返回對應的IPackageFragment
常用工具類
() JavaCore(定義在re包下)
JavaCore從Plugin繼承它是JDT插件的生命周期管理器不過對於第三方插件開發人員來說它的重要性更多地體現在它提供的一些工具類方法中
IJavaElement create(IFile file)從文件創建對應的Java元素
IJavaElement create(IFolder folder)從文件夾創建對應的Java元素
IJavaProject create(IProject project)得到IProject對應的IJavaProject
IJavaElement create(IResource resource)從資源創建對應的Java元素
IJavaModel create(IWorkspaceRoot root)從工作空間根目錄得到對應的IJavaModel
IClassFile createClassFileFrom(IFile file)從文件創建對應的IClassFile
ICompilationUnit createCompilationUnitFrom(IFile file)從文件創建對應的ICompilationUnit
() JavaUI(定義在orgeclipsejdtui包下)
JavaUI中定義了常用的Java插件界面相關的方法
createPackageDialog創建一個包選擇對話框返回值是SelectionDialog
createTypeDialog創建一個類型選擇對話框返回值是SelectionDialog
IEditorPart openInEditor(IJavaElement element)用編輯器打開指定的Java元素並返回編輯器實例
revealInEditor(IEditorPart part IJavaElement element)在編輯器中定位元素element
插件開發中經常會碰到一些常用的技巧掌握這些技巧可以極大地提高插件的開發效率並且可以減小插件的體積下面列出一些常見的技巧
() 由一個普通項目得到Java項目
Java項目是一種特殊的項目需要注意的是IJavaProject並不是從IProject繼承的不能將一個IProject對象強制轉換成一個IJavaProject對象也不能把一個IJavaProject實例賦值給IProject變量
由IProject項目得到Java項目的方式
IJavaProject javaPoject = JavaCorecreate(IProject);
由IJavaProject得到IProject的方式
調用IJavaProject的IProject getProject();
()得到工作空間中的所有Java項目
我們可以首先得到工作空間中的所有項目然後逐個進行轉換不過這不免麻煩了一些下面介紹更好的方式IJavaModel是所有Java項目的根通過它就可以得到所有的Java項目
IWorkspaceRoot root = ResourcesPlugingetWorkspace()getRoot(); IJavaModel jModel = JavaCorecreate(root); IJavaProject jProject[] = jModelgetJavaProjects();
() 打開Java編輯器並顯示Java編譯單元的特定成員
代碼如下
void showMethod(IMember member) { ICompilationUnit cu = membergetCompilationUnit(); IEditorPart javaEditor = JavaUIopenInEditor(cu); JavaUIrevealInEditor(javaEditor member); }
() 在工程下創建一個wnew包並創建一個Hellojava文件
() 打開【打開類型】對話框
以下代碼段使用 JavaUI 類來打開【打開類型】對話框
new ProgressMonitorDialog(parent) SearchEnginecreateWorkspaceScope()
用類似方法還可以創建【打開包】和【打開主要類型】對話框
() 打包指定的文件
我們寫一些工具的時候也許需要把文件打成jar包然後進行發布到應用服務器等操作調用JDT提供的類可簡化這個操作(用到的打Jar包的類都在orgeclipseuijarpackager下)
JarPackageData description= new JarPackageData(); IPath location= new Path(C:/cownewjar); descriptionsetJarLocation(location); descriptionsetSaveManifest(true); descriptionsetManifestMainClass(mainType); descriptionsetElements(filestoExport); IJarExportRunnable runnable= descriptioncreateJarExportRunnable(parentShell); new ProgressMonitorDialog(parentShell)run(truetrue runnable);
參數mainType表示Jar包的main類filestoExport為要打包的文件
() 自動設置Java項目的構建路徑
有一些插件會將需要的jar包自動設置到構建路徑上比如使用WTP的新建向導新建web項目的時候就會把web開發需要的jar包自動放入項目的構建路徑使用PDE的將項目轉換為插件項目功能後項目的構建路徑中就增加了插件依賴項的庫那麼它們是怎麼實現的呢?
Java項目的構建路徑有如下幾種源文件夾二進制庫依賴項目類路徑變量和類路徑容器
圖 源文件夾
圖 構建依賴項目
圖 Jar和類文件夾依賴
每種不同的構建路徑都有不同的作用源文件夾是把源碼進行構建的途徑二進制庫是導入少量jar包的方式依賴項目是供多項目分模塊開發使用的使用類路徑變量可以避免二進制包的路徑依賴而類路徑容器則為大量二進制庫的引入提供了方便
JDT為這些不同的構建路徑提供了一個統一的接口IClassPathEntry只要調用IJavaProject的setRawClasspath方法就可以為項目設定構建路徑
可以看到setRawClasspath方法需要一個IClasspathEntry數組數組中的元素就是要設置的每一個構建路徑前面提到的JavaCore類提供了一系列的靜態方法來幫助我們生成不同的IClasspathEntry而無須關注生成的細節下面來看不同構建路徑的添加方式
① 源文件夾使用JavaCorenewSourceEntry方法下面的代碼的作用是構造項目MyProject的源文件夾src的類路徑條目
JavaCorenewSourceEntry(new Path(/MyProject/src));
② 二進制庫IClasspathEntry使用JavaCorenewLibraryEntry 方法下面的代碼就是構造MyProject的類文件lib的類路徑條目
Path(/MyProject/lib)null nullfalse);
以下類路徑條目具有源代碼連接
設定關聯源代碼包有利於代碼的跟蹤調試
③ 依賴項目使用JavaCorenewProjectEntry方法下面的代碼就是構造依賴項目MyFramework
IClassPathEntry prjEntry = JavaCorenewProjectEntry(new
Path(/MyFramework) true);
④ 類路徑變量使用JavaCorenewVariableEntry方法類路徑變量對於整個工作空間來說是全局的並且可以通過 JavaCore 方法 getClasspathVariable 和 setClasspathVariable 來處理
可能會注冊自動的類路徑變量初始化方法當啟動工作空間時通過擴展點 orgeclipse reclasspathVariableInitializer來調用該類路徑變量初始化方法
以下類路徑條目指示一個庫該庫的位置存放在變量HOME中使用變量SRC_HOME和SRC_ROOT來定義源代碼連接
IClassPathEntry varEntry = JavaCorenewVariableEntry(
new Path(HOME/foojar) //庫路徑
new Path(SRC_HOME/foo_srczip) //源碼歸檔路徑
new Path(SRC_ROOT) //源碼歸檔根路徑
true);
JavaCoresetClasspathVariable(HOME new Path(d:/myInstall) null);
⑤ 類路徑容器通過 JavaCore的getClasspathContainer和setClasspathContainer兩個方法來處理類路徑容器
可能會注冊一個自動的類路徑容器初始化方法當需要綁定容器時通過擴展點 reclasspathContainerInitializer來被動地調用類路徑容器初始化方法
以下類路徑條目指示系統類庫容器
IClassPathEntry varEntry = JavaCorenewContainerEntry( new Path(JDKLIB/default)false); JavaCoresetClasspathContainer( new Path(JDKLIB/default) new IJavaProject[]{ myProject } new IClasspathContainer[] { new IClasspathContainer() { public IClasspathEntry[] getClasspathEntries() { return new IClasspathEntry[]{ JavaCorenewLibraryEntry( new Path(d:/rtjar) null null false); }; } public String getDescription() { return Basic JDK library container; } public int getKind() { return IClasspathContainerK_SYSTEM; } public IPath getPath() { return new Path(JDKLIB/basic); } } } null);
我們只要調用相應的方法創建我們的類路徑條目就可以了然後把這些條目組成的數組通過setRawClasspath方法設定到項目中需要注意的是如果我們只把要添加的類路徑條目傳入 setRawClasspath方法的話就會替換原有的項目構建路徑這常常是我們不希望的可以調用IJavaProject的 readRawClasspath方法讀取項目已有的設置把我們要設置的構建路徑添加到它的後面然後再調用setRawClasspath方法設定新的項目構建路徑
在這個例子中將要實現一個為項目添加 lucene支持的功能用戶在項目上右擊選擇菜單中的【為項目添加lucene支持】命令以後插件就會把lucene的jar包和源碼包復制到項目的lib目錄下並且將jar包加入構建路徑如圖所示為增加lucene支持前的項目結構
圖 增加lucene支持之前的項目結構
用戶在項目上右擊在彈出的快捷菜單中選擇【為項目添加lucene支持】命令後的項目結構如圖所示
圖 增加lucene支持之後的項目結構
圖是項目的構建路徑
圖 增加的lucene包
首先新建一個插件工程並將JDT相關的依賴項加入然後添加一個orgeclipseuipopupMenus的擴展點如果不熟悉怎麼添加可以使用插件向導中的彈出菜單向導
需要注意contribution的配置如圖所示
圖 contribution的配置
此插件只針對Java項目起作用因此 objectClass中填入reIJavaProject;adaptable選擇true;如果是用向導生成的那麼請記住清空nameFilter下面是核心類ActionAddLucene的實現代碼
SystemgetProperty(fileseparator/); JavaCorenewLibraryEntry(project getFullPath() project LUCENESRCJAR)getFullPath() null new IClasspathEntry[oldPathslength + ]; LIB + FILESEPARATOR + LUCENEJAR); LIB + FILESEPARATOR + LUCENESRCJAR); IClasspathEntry entry) egetMessage() e));
下面解釋一下代碼中的重點部分
IClasspathEntry[] oldPaths = javaProjectreadRawClasspath();
讀取項目原有的構建路徑條目
IClasspathEntry luceneLibEntry = JavaCorenewLibraryEntry( projectgetFile(LIB + FILESEPARATOR + LUCENEJAR)getFullPath() projectgetFile(LIB + FILESEPARATOR + LUCENESRCJAR)getFullPath() null false);
這一句構建lucene的jar包
第個參數是二進制jar包的位置我們的二進制jar包的位置為項目路徑下的lib/lucenesrcjar
第個參數是jar包對應的源碼包的位置
第個參數為源碼包的根路徑因為有的源碼jar包的源碼根路徑不是jar包的根路徑比如simplejta的源碼jar包的格式如圖所示
圖 Jar包的結構
對於這種情況就要指定第個參數為srclucene的源碼包的源碼根路徑就是jar包的根路徑因此我們設置此參數為null
第個參數表示是否導出我們設置為false
() URL luceneLib = ActivatorgetDefault()getBundle()getEntry(RESOUCELIB + FILE SEPARATOR + LUCENEJAR);
我們把lucenejar lucenesrcjar放到我們插件的resoucelib目錄下當用戶單擊【為項目添加lucene支持】的時候要把這兩個文件復制到項目的lib目錄下因此需要首先讀取插件路徑resoucelib目錄下的這兩個jar包
讀取插件路徑下的文件時我們使用插件Activator類提供的方法即可比如如下調用
就可以讀取到插件根目錄下的文件config/myxml返回類型是URL
() copyURLToFile(luceneLib project LIB + FILESEPARATOR + LUCENEJAR);
ActivatorgetDefault()getBundle()getEntry讀取到的文件位置是URL類型的我們需要把這個URL對應的文件復制到項目的lib下下面看一下copyURLToFile的主干代碼
URL類有一個openStream可以打開文件的輸入流IFile也有一個接受輸入流的create方法用來創建文件因此我們只需要把url的輸入流輸出給IFile的create方法即可
這裡我們也可以由url得到其對應的磁盤上的路徑也可以得到IFile對應的磁盤上的路徑然後使用Java IO來進行文件復制操作但是這樣做不僅代碼數量變多了而且由於使用的不是Eclipse的資源管理API會帶來無法自動刷新等問題因此建議盡量使用Eclipse提供的API來完成此功能
學習Eclipse插件開發的最好的方式就是研讀 Eclipse的源碼而對插件開發者最有參考價值的就是JDT(Java Development Tools)的代碼相信把所有的包研讀一遍以後就會成為插件開發的高手了下面是各個主要包的內容讀者可以根據需要有選擇地進行研讀
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28129.html