??xml version="1.0" encoding="utf-8" standalone="yes"?>
于是,只好用最原始的办?看Eclipse的源代码.最后一些跟decorator相关的类引v了我的注?q发现有一个相关的LabelProvider.于是我用q个词作为关键字搜烦C下面q篇文章,觉得十分有用,所以暂存到q里.
原文标题: org.eclipse.ui.decorators得用?br />
<extension point="org.eclipse.ui.decorators">
<decorator icon="icons/warning_small.gif" id="cnooc.rcp.decorator.node.warning" label="Data Warning Decorator" lightweight="true" location="BOTTOM_LEFT" state="true">
<enablement>
<and>
<objectClass "com.eplat.cnooc.rcp.node.INode"/>
<objectState name="hasWarning" value="true"/>
</and>
</enablement>
</decorator>
<decorator icon="icons/error_small.gif" id="cnooc.rcp.decorator.node.error" label="Data Error Decorator" lightweight="true" location="BOTTOM_LEFT" state="true">
<enablement>
<and>
<objectClass "com.eplat.cnooc.rcp.node.INode"/>
<objectState name="hasError" value="true"/>
</and>
</enablement>
</decorator>
</extension>
INode是TreeViewer里面节点得对?
Viewer讄LabelProvider旉要如?
viewer.setLabelProvider(new DecoratingLabelProvider(new ViewLabelProvider(),
Activator.getDefault().getWorkbench().getDecoratorManager().getLabelDecorator()));
写了q个以后q没? 需要让INode实现IActionFilter接口. eclipse得API中说要么实现IActionFilter接口, 要么实现IAdapter接口, 如果实现后者得? pȝ会调用getAdapter()Ҏ. 不过我还是选择前?
/**
* (non-Javadoc)
*
* @see org.eclipse.ui.IActionFilter#testAttribute(java.lang.Object, java.lang.String,java.lang.String)
*/
public boolean testAttribute(Object target, String name, String value){
if (name.equals("hasWarning")){
return !getProblems().hasError() && getProblems().hasWarning();
} else if (name.equals("hasError")){
return getProblems().hasError();
}
return false;
}
意思应该比较明昑־, 如果有warningq且没有error得时候warning得decorator生效. 如果有error则error得decorator生效. name参数对应得就是objectState得name参数. value参数对应得objectState得value参数. target参数是viewer中得节点对象, 不过׃INode实现了IActionFilter接口, 因此q里得target是this?
一般来说需要判断得是Ҏname获取得值是否等于value, {于q回true, 否则q回false. 不过q里我不需要判断这个了, 直接Ҏ当前状态返回就好了.
按照eclipse得原? 理论上应该INode变化以后viewer׃跟着变化, 但是我实验下来有时候好有时候不?
因此在Editor得verifyҎ里增加了下面得逻辑:
/**
* 校验数据
*
* @return
*/
private boolean verify(){
//校验数据
//不管是否有error或者warning都需要通知向导树刷C下节?
ExplorerView view = (ExplorerView) getSite().getPage().findView(ExplorerView.class.getName());
view.refresh((INode) getEditorInput());
return true;
}
现在好了, 只要执行verifyҎ, viewer׃h对应得节? 以达到显C左下方图标得目的.
原文地址: http://blog.csdn.net/bradwoo8621/archive/2007/05/11/1604738.aspx
作者:李红?2005-8-13
本文章允许{?但请要求注明文章作者及出处
一 创徏插g目
创徏一个插仉目example.my.treeviewQ这个例子将向eclipse贡献一个视图,q个视图采用树(TreeviewerQ来实现?br />
下图是本例的文g清单
<抱歉,囄传不上来>
+ example.my.treeview
+ src
+ example.my.treeview
- TreeviewPlugin.java
+ exampe.my.treeview.data
- CityEntity.java
- CountryEntity.java
- DataFactory.java
- PeopleEnrity.java
+ example.my.treeview.internal
- ITreeEntry.java
- TreeViewerContentProvider.java
- TreeViewerLabelProvider.java
- TreeViewPart.java
+ JRE System Library
+ Plug-in dependencies
+ META-INF
- MENIFEST.MF
- build.properties
- plugin.xml
?准备数据模型
首先我们准备数据模型Q这些数据模型都保存在example.my.treeview.dataq个包中
我们定义一个接口ItreeEntryQ这个接口将定义树中每个节点共同特征Q名U和子节点)Q代码如?br />
package example.my.treeview.internal;
import java.util.List;
public interface ITreeEntry {
public String getName();
public void setName(String name);
//讄得到子节点的集合
public void setChildren(List children);
public List getChildren();
}
q里涉及的实体一共有3个,以下是他们的代码
package example.my.treeview.data;
import java.util.List;
import example.my.treeview.internal.ITreeEntry;
public class CityEntity implements ITreeEntry{
private Long id;//唯一识别?br /> private String name;//城市?br /> private List peoples;//城市中的?br /> public CityEntity(){}
public CityEntity(String name){this.name=name;}
public Long getId() {return id;}
public void setId(Long id) {this.id = id;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public List getChildren() {return peoples;}
public void setChildren(List peoples) {
this.peoples = peoples;
}
}
package example.my.treeview.data;
import java.util.List;
import example.my.treeview.internal.ITreeEntry;
public class CountryEntity implements ITreeEntry{
//唯一识别码,在数据库里常动递增的ID?br /> private Long id;
private String name;//国家?br />//此国家所包含的城市的集合Q集合元素ؓCity对象
private List cities;
//两个构造函?br /> public CountryEntity(){}
public CountryEntity(String name){this.name = name;}
//相应的get和setҎ
public List getChildren() {return cities;}
public void setChildren(List cities) {this.cities = cities;}
public Long getId() {return id;}
public void setId(Long id) {this.id = id;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
}
package example.my.treeview.data;
import java.util.List;
import example.my.treeview.internal.ITreeEntry;
public class PeopleEntity implements ITreeEntry{
private String name;
public PeopleEntity(){}
public PeopleEntity(String name){this.name=name;}
public List getChildren(){return null;}
public void setChildren(List children){}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
}
?创徏树中的数据结?br />
代码如下
package example.my.treeview.data;
import java.util.ArrayList;
public class DataFactory {
public static Object createTreeData(){
//生成人的数据对象
PeopleEntity p1 = new PeopleEntity("李红?);
PeopleEntity p2 = new PeopleEntity("金利?);
PeopleEntity p3 = new PeopleEntity("何涛");
//生成城市的数据对?br /> CityEntity city1=new CityEntity("湖北");
CityEntity city2=new CityEntity("北京");
CityEntity city3=new CityEntity("湖南");
//生成国家的数据对?br /> CountryEntity c1 = new CountryEntity("国");
CountryEntity c2 = new CountryEntity("中国");
//数据对象连接v?br /> //人和城市的关p?br /> {
ArrayList list = new ArrayList();
list.add(p1);
city1.setChildren(list);
}
{
ArrayList list = new ArrayList();
list.add(p2);
city2.setChildren(list);
}
{
ArrayList list = new ArrayList();
list.add(p3);
city3.setChildren(list);
}
//城市和国家的关系
{
ArrayList list = new ArrayList();
list.add(city1);
c1.setChildren(list);
}
{
ArrayList list = new ArrayList();
list.add(city2);
list.add(city3);
c2.setChildren(list);
}
//国家置于一个对象之下,
//q个对象可以是List也可以是数组
{
ArrayList list = new ArrayList();
list.add(c1);
list.add(c2);
return list;
}
}
}
?标签器和内容?br />TreeViewer和TableViewer一P是用内容器和标签器来控制记录对象的显C,q且使用内容器和标签器的语句也是一L?br />
下面是标{֙的代?br />
package example.my.treeview.internal;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.swt.graphics.Image;
/**
* @author hopeshared
* 标签提供器,控制U录在树中显C的文字和图像等
*/
public class TreeViewerLabelProvider
implements ILabelProvider{
//U录昄 的文字,不能q回null
public String getText(Object element){
ITreeEntry entry = (ITreeEntry)element;
return entry.getName();
}
//U录昄的图?br /> public Image getImage(Object element){
return null;
}
//以下Ҏ暂不用,I实?br /> public void addListener(ILabelProviderListener listener){}
public void dispose(){}
public boolean isLabelProperty(Object e, String p){return false;}
public void removeListener(ILabelProviderListener listen){}
}
下面是内容器的代?br />
package example.my.treeview.internal;
import java.util.List;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;
/**
* @author hopeshared
* 内容器,由它军_哪些对象应该输出在TreeViewer里显C?br />*/
public class TreeViewerContentProvider
implements ITreeContentProvider{
//pU方法决定树的哪一U显C哪些对?br /> public Object[] getElements(Object inputElement)
{
if(inputElement instanceof List){
List list = (List)inputElement;
return list.toArray();
}else{
return new Object[0];//生成一个空的数l?br /> }
}
//判断某节Ҏ否有子节点,如果有子节点Q?br />//q时节点前都有一个?”号图标
public boolean hasChildren(Object element){
ITreeEntry entry = (ITreeEntry)element;
List list = entry.getChildren();
if(list==null||list.isEmpty()){return false;
}else{return true;}
}
//p个方法来军_父节点应该显C哪些子节点
public Object[] getChildren(Object parentElement){
ITreeEntry entry = (ITreeEntry)parentElement;
List list = entry.getChildren();
if(list==null || list.isEmpty()){return new Object[0];
}else{return list.toArray();}
}
//以下ҎI实?br /> public Object getParent(Object element){return null;}
public void dispose(){}
public void inputChanged(Viewer v, Object oldInput, Object newInput){}
}
?修改清单文g
下面l出的是plugin.xml文g代码
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin>
<extension point="org.eclipse.ui.views">
<view
class="example.my.treeview.internal.TreeViewPart"
id="example.my.treeview.treeview"
name="my first tree view plugin"/>
</extension>
</plugin>
?插g的实?br />在清单文件中已经指出了这个视囄实现cLexample.my.treeview.internal.TreeViewPartQ下面给个文件的代码
package example.my.treeview.internal;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;
import example.my.treeview.data.DataFactory;
public class TreeViewPart extends ViewPart{
public void createPartControl(Composite parent){
Composite topComp = new Composite(parent, SWT.NONE);
topComp.setLayout(new FillLayout());
TreeViewer tv = new TreeViewer(topComp, SWT.BORDER);
tv.setContentProvider(new TreeViewerContentProvider());
tv.setLabelProvider(new TreeViewerLabelProvider());
Object inputObj = DataFactory.createTreeData();
tv.setInput(inputObj);
}
public void setFocus(){}
}
?q行l果
<抱歉,囄上传p|>
?l节点增加动?br />增加一个ActionGroupc?br />
package example.my.treeview.internal;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.ui.actions.ActionGroup;
/**
* @author hopeshared
* 生成菜单MenuQƈ两个Action传入
*/
public class MyActionGroup extends ActionGroup{
private TreeViewer tv;
public MyActionGroup(TreeViewer treeViewer){
this.tv = treeViewer;
}
//生成菜单MenuQƈ两个Action传入
public void fillContextMenu(IMenuManager mgr){
//加入两个Action对象到菜单管理器
MenuManager menuManager = (MenuManager)mgr;
menuManager.add(new OpenAction());
menuManager.add(new RefreshAction());
//生成Menuq挂在树Tree?br /> Tree tree = tv.getTree();
Menu menu = menuManager.createContextMenu(tree);
tree.setMenu(menu);
}
//打开Actionc?br /> private class OpenAction extends Action{
public OpenAction(){
setText("打开");
}
//l承自Action的方法,动作代码写在此方法中
public void run(){
IStructuredSelection selection = (IStructuredSelection)tv.getSelection();
ITreeEntry obj = (ITreeEntry)(selection.getFirstElement());
if(obj != null){
MessageDialog.openInformation(null, null, obj.getName());
}
}
}
//h的Actionc?br /> private class RefreshAction extends Action{
public RefreshAction(){
setText("h");
}
//l承自Action的方法,动作代码写在此方法中
public void run(){
tv.refresh();
}
}
}
接着Q修改TreeViewPart.javaQ代码如?br />
…?br />Object inputObj = DataFactory.createTreeData();
//-------------加入动作开?br /> MyActionGroup actionGroup = new MyActionGroup(tv);
actionGroup.fillContextMenu(new MenuManager());
//-------------加入动作l束
tv.setInput(inputObj);
…?br />
l果如下图所C?br /><抱歉,囄上传不成?gt;
?自定义扩展点
我们惛_q个视图的显C内容与视图框架分开Q这P我们需要修改视图显C内容的时候只要重新A献一ơ显C内容就可以了?br />9.1 dshema文g
q个sheme文g是采用可视化~辑器进行编辑,然后pde自动生成的,代码如下
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="example.my.treeview">
<annotation>
<appInfo>
<meta.schema plugin="example.my.treeview" id="datafactory" name="Data Factory"/>
</appInfo>
<documentation>
[Enter description of this extension point.]
</documentation>
</annotation>
<element name="extension">
<complexType>
<sequence><element ref="factory"/></sequence>
<attribute name="point" type="string" use="required">
<annotation><documentation></documentation></annotation></attribute>
<attribute name="id" type="string">
<annotation><documentation></documentation></annotation></attribute>
<attribute name="name" type="string">
<annotation><documentation></documentation>
<appInfo><meta.attribute translatable="true"/></appInfo></annotation>
</attribute>
</complexType>
</element>
<element name="factory">
<complexType>
<attribute name="id" type="string">
<annotation><documentation></documentation></annotation></attribute>
<attribute name="name" type="string">
<annotation><documentation></documentation></annotation></attribute>
<attribute name="class" type="string" use="required">
<annotation><documentation></documentation></annotation></attribute>
</complexType>
</element>
<annotation>
<appInfo><meta.section type="since"/></appInfo>
<documentation>[Enter the first release in which this extension point appears.]
</documentation>
</annotation>
<annotation>
<appInfo><meta.section type="examples"/></appInfo>
<documentation>[Enter extension point usage example here.]</documentation>
</annotation>
<annotation>
<appInfo><meta.section type="apiInfo"/></appInfo>
<documentation>[Enter API information here.]</documentation></annotation>
<annotation>
<appInfo><meta.section type="implementation"/></appInfo>
<documentation>
[Enter information about supplied implementation of this extension point.]
</documentation></annotation>
<annotation>
<appInfo><meta.section type="copyright"/></appInfo>
<documentation></documentation></annotation>
</schema>
9.2 创徏接口文g
ItreeEntry.java之前已l创建好了,不需要修攏V现在添加另一个接口文Ӟ代码如下Q?br />
package example.my.treeview.internal;
public interface IDataFactory {
public Object createTreeData();
}
于是我们修改DataFactory.javaQ它实现这个接口?br />9.3 修改清单文g
我们来修Ҏ单文Ӟ加入扩展点声明,q扩展它Q代码如?br />
…?br /><extension-point id="datafactory" name="Data Factory"
schema="schema/datafactory.exsd"/>
<extension point="example.my.treeview.datafactory">
<factoryclass="example.my.treeview.data.DataFactory"/>
</extension>
…?br />
9.4 修改TreeviewPlugin.java
增加一个方法Object loadDataFactory()Q代码如?br />
…?br />public static Object loadDataFactory(){
IPluginRegistry r=Platform. getPluginRegistry();
String pluginID="example.my.treeview";
String extensionPointID="datafactory";
IExtensionPoint p=r.getExtensionPoint( pluginID, extensionPointID);
IConfigurationElement[] c=p.getConfigurationElements();
if( c != null) {
for( int i= 0; i <c.length; i++) {
IDataFactory data = null;
try { data=( IDataFactory)c
.createExecutableExtension("class");
if( data != null){ return data.createTreeData(); }
} catch( CoreException x) { }}}
return new Object();
}
…?br />
9.5 修改TreeViewPart.java
?br />Object inputObj = DataFactory.createTreeData();
替换?br />Object inputObj = TreeviewPlugin.loadDataFactory();
9.6 其他辅助文g
其实TreeViewerLabelProvider.java和TreeViewerContentProvider.java可以看成是对DataFactoryq个扩展点的辅助文g
9.7q行
跟之前的实现没有区别Q但是我们向eclipse贡献了一个扩展点
?参考资?br />《Eclipse入门到精通?br />
www.sohozu.com
《自己动手编写Eclipse扩展炏V?br />EclipseCon2005_Tutorial1.pdf 《Contributing to Eclipse: Understanding and WritingPlug- ins?/em>
囄Q?
囄Q?
l过一个多时的努力。。。(嘿嘿Q以前没有仔l研IProperty什么的Q今天弄了一下)
l于出现了propertyq且可以修改属性页中的?br />
代码
example.my.treeview.rar
哦,补充一下,׃模型Q就是treeviewer中的初始数据Q是写死的,改的property其实是修改了内存中的对象的倹{假如用emf做模型持久化Q就会保存修攏V但是目前是不能保存修改的?/font>
关于本文的讨是很多的Q也有很多有用的信息。见http://www.eclipseworld.org/bbs/read.php?tid=168
本文W一ơ发表是在社Z中,本来也没觉得有{到blog的必要,但是后来发觉自己的记忆力来差Q曾l作q的都忘记的差不多了Qؓ了避免丢失,q是存在q里备䆾比较好?img src ="http://m.tkk7.com/hopeshared/aggbug/59983.html" width = "1" height = "1" />
eclipse上有一个SOA的项目,但是q没有第一个版本出来,管用cvsq上了服务器得到了源代码Q可以握q是不会q行Q呵呵,可能是我比较W?
机器上RSA和WAS都有了,但是q是不能开发BPELQ查了下资料Q似乎可以用WSAD来创建BPELQ也可以用Rational XSD来从UML导出BPELQ然后在WPS中运行BPEL
{我的机器装上上面的装备Q估计就动不了了Q于是我四处L更简单的开发BPEL的方?br />
接下来就扑ֈ了Oracle的JDeveloperQ这个工Lhq挺清爽Q但是可惜还是不能创建BPELQ原来它需要Oracle的BPEL~辑器插件。接着在Oracle的站点上扑ֈ了这个工P却发现它居然也有Eclipse的插Ӟ于是安装了一个Eclipse插g?br />
q个BPEL~辑器运行的效果看v来还不错Q但是只能编辑BPELQ运行的时候还需要装Oracle的BPEL ServerQ?omgQ我发现自己又差点上了“贼船”,q么装下M计我q要把Oracle他们家的所有Y仉装一遍,于是攑ּQl寻?br />
最后不知道在哪里看Cq个链接: http://www.eclipse.org/bpelQ这个链接挺眼生 Q没去过Q这不,一上去发C新大?br />
从这个项目的介绍上看跟Oracle的BPEL~辑器能力差不多Q不知道是否能运行BPEL。假如不行的话,q有STP的B2J目可以q行BPEL
看来q是有很多h致力于服务集成的Q呵?img src ="http://m.tkk7.com/hopeshared/aggbug/42826.html" width = "1" height = "1" />
W一U:利用Action
IWorkbenchWindow window = getViewSite().getWorkbenchWindow();
IWorkbenchAction max = ActionFactory.MAXIMIZE.create(window);
max.run();
q段代码要放在何适的位置上才会v到合适的作用?br />
W二U:利用Zoom
在ApplicationWorkbenchWindowAdvisor#postWindowOpen中做?br />public void postWindowOpen() {
IWorkbenchWindow window = Plugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
IViewPart part=null;
try {
part = window.getActivePage().showView(View.ID);
} catch (PartInitException e) {
e.printStackTrace();
}
if(part!=null){
window.getActivePage().activate(part);
window.getActivePage().bringToTop(part);
WorkbenchPage realPage = (WorkbenchPage) window.getActivePage();
IWorkbenchPartReference partRef = window.getActivePage().getActivePartReference();
if (partRef != null) {
((WorkbenchPage) window.getActivePage()).toggleZoom(partRef);
}else{
System.out.println("partRef is null!");
}
}
}
Dynamic awareness requires extra steps that were not required prior to the introduction of dynamic plug-ins. Dynamic awareness requires that you remove all references to classes defined in other plug-ins when those plug-ins are removed from the system. In particular, if your plug-in defines extension points that load classes from other plug-ins—executable extensions—you need to discard those references when other plug-ins are dynamically removed. The extension registry allows you to add a listener that notifies you when extensions are being added or removed from the system. If your plug-in maintains its own cache of extensions that are installed on your extension point, your listener should update this cache for each added or removed extension.
The following is an example of a simple class that maintains its own cache of the set of extensions installed for a given extension point. This example is a bit contrived as simply caching the extension objects has no value. Typically, your plug-in will process the extensions to extract useful information and possibly load one or more classes associated with that extension. The basic structure of this cache example is as follows:
public class ExtCache implements IRegistryChangeListener { private static final String PID = "my.plugin"; private static final String PT_ID = PID + "." + "extension.point"; private final HashSet extensions = new HashSet(); ... }
The extensions field stores the set of installed extensions for a particular extension point.
The cache has a startup method that loads the initial set of extensions and then adds an extension registry listener in order to be notified of future changes:
public void startup() { IExtensionRegistry reg = Platform.getExtensionRegistry(); IExtensionPoint pt = reg.getExtensionPoint(PT_ID); IExtension[] ext = pt.getExtensions(); for (int i = 0; i < ext.length; i++) extensions.add(ext[i]); reg.addRegistryChangeListener(this); }
The class implements the IRegistryChangeListener interface, which has a single method that is called whenever the registry changes:
public void registryChanged(IRegistryChangeEvent event) { IExtensionDelta[] deltas = event.getExtensionDeltas(PID, PT_ID); for (int i = 0; i < deltas.length; i++) { if (deltas[i].getKind() == IExtensionDelta.ADDED) extensions.add(deltas[i].getExtension()); else extensions.remove(deltas[i].getExtension()); } }
This class is now dynamic aware but is not yet dynamic enabled; that is, the class does not yet support itself being dynamically removed. The final step is to implement a shutdown method that clears all values from the cache and removes the listener from the extension registry:
public void shutdown() { extensions.clear(); IExtensionRegistry reg = Platform.getExtensionRegistry(); reg.removeRegistryChangeListener(this); }
This shutdown method must be called from the shutdown method of the plug-in that defines the cache. For the complete source code of this example, see the ExtCache class in the FAQ Examples plug-in.
Note that not only extensions points acquire and maintain references to classes defined in other plug-ins. You need to be especially aware of static fields and caches that contain references to objects whose class is defined in other plug-ins.
If you hold onto classes defined in other plug-ins through different mechanisms, you also need to discard those references when those other plug-ins are removed.
原文地址Q?a >http://wiki.eclipse.org/index.php/FAQ_How_do_I_make_my_plug-in_dynamic_aware%3F
得把org.eclipse.ui/SHOW_TRADITIONAL_STYLE_TABS=false加在plugin_customization.ini里头
plugin_customization.iniq可以定制不东西,q个文g要自己创建的吧,RCPE序里面没有
在plugin.xmlQorg.eclipse.core.runtime.products下的产品加上一个属性?BR>name: preferenceCustomization
value: plugin_customization.ini
然后在工E中加上plugin_customization.ini q文件。内ҎQ?BR>org.eclipse.ui/SHOW_TRADITIONAL_STYLE_TABS=false
<property name="preferenceCustomization" value="plugin_customization.ini"/>
plugin_customization.ini
, in the same directory as the plugin.xml
file, with contents of the form: <pluginId>/<preferenceName>=<preferenceValue>
plugin_customization.ini
file: org.eclipse.ui/DOCK_PERSPECTIVE_BAR=left org.eclipse.ui/SHOW_TEXT_ON_PERSPECTIVE_BAR=false org.eclipse.ui/initialFastViewBarLocation=left org.eclipse.ui/SHOW_TRADITIONAL_STYLE_TABS=false
通过文g得到ProjectQ?/P>
通过文g得到全\径:
得到整个Workspace的根Q?/P>
从根来查找资源:
从Bundle来查找资源:
得到Appliaction workspaceQ?/P>
Platform.asLocalURL(PRODUCT_BUNDLE.getEntry("")).getPath()).getAbsolutePath();
得到runtimeworkspaceQ?BR>
Platform.getInstanceLocation().getURL().getPath();
从编辑器来获得编辑文?BR>
单地_SDO是一U数据应用程序开发框Ӟ它包括一个体pȝ构和相应?API。SDO 能够实现以下操作Q?/P>
在这介l?SDO 框架的文章中Q我们将试着解释 SDO 背后的动机,以及 SDO 与其他规范的区别Q然后描q?SDO 的组成,最后,通过一个示?SDO 应用E序说明 SDO 的用法?/P>
Z么要使用 SDOQ?/SPAN>
对于服务数据对象QSDOQ,大多数开发h员要问的W一个问题就是ؓ什么要使用 SDO。难?J2EE 本nq不够庞大、不够复杂(而且难以掌握Q吗QJava 环境中不是已l有其他支持 XML 的框架了吗?所q的是,该问题的{案能够让我们多Ch感到满意QSDO 是作为简?J2EE 数据~程模型的方法出现的Q它能够?J2EE 开发h员把更多的时间用于应用程序的业务逻辑?/P>
服务数据对象框架为数据应用程序开发提供了l一的框架。通过 SDOQ您不需要熟悉特定于技术的 APIQ就能访问和利用数据。您只需要知道一U?APIQ即 SDO APIQ它允许您处理来自多U数据源的数据,其中包括关系数据库、实?EJB lg、XML 面、Web 服务、Java Connector Architecture、JavaServer Pages 面{?/P>
注意Q我们用了 框架q一词。这是比?Eclipse 框架的说法。由于设计的基础坚固而且可以扩展Q所?Eclipse 能够集成各种工具。与此类|对于采用 SDO 的应用程序,SDO 也是一U框Ӟq类应用E序?SDO 模型上是一致的?
与其他某些数据集成模型不同的是,SDO 没有停留在数据抽象上。SDO 框架q结合了很多 J2EE 模式和最佛_践,从而应用E序很容易结合经q验证的体系l构和设计。比方说Q今天的多数 Web 应用E序癑ֈ之百的时间没有(或不能)q接到后端系l,因此 SDO 支持不连接的~程模型。同LQ今天的应用E序往往非常复杂Q包含很多层ơ。如何存储数据、如何发送数据、如何在 GUI 框架中将它们提供l终端用PSDO ~程模型提供的应用模式能够清晰地划分不同的问题?/P>
XML 在分布式应用E序中日渐普及。比如,XML Schema (XSD) 被用来定义应用程序数据格式中的业务规则。XML 本n也可以用于改q交互性:Web 服务使用Z XML ?SOAP 作ؓ消息格式。XML 是推?SDO 的一个重要原因,SDO 框架支持q成了 XML?/P>
各种技术的比较
前面已经提到QSDO q不是提军_布式应用E序中数据集成问题的惟一技术。下面将分别讨论 SDO 和类似的~程框架 JDO、JAXB ?EMF 的优劣?/P>
SDO ?WDO
Web 数据对象Q或 WDOQ是随着 IBM WebSphere] Application Server 5.1 ?IBM WebSphere Studio Application Developer 5.1.2 发布?SDO 早期版本的名U。如果用过 WebSphere Studio 5.1.2Q那么您?SDO 可能已经有所了解Q虽然您可能习惯看到它标记?WDOQ比如在数据库的名字中。忘?WDO 吧,它现在的名字?SDOQ?/P>
SDO ?JDO
JDO 代表 Java Data ObjectQJava 数据对象Q。JDO 已经通过 Java Cq程QJCPQ标准化?1.0 版,2003 q?5 月推Zl护?1.0.1Q现在已lؓ 2.0 版成立了 JCP 专家l。JDO 针对 Java 环境中的数据~程提供了一U通用 APIQ用于访问存储在不同数据源中的数据,如数据库、文件系l或者事务处理系l。JDO 保持?Java 对象Q图Q之间的关系Q同时允许对数据的ƈ发访问?/P>
JDO 希望化和l一 Java 数据~程Q以便开发h员能够专注于业务逻辑Q而不是底层的技术,从这一点上_其目标和 SDO 是相同的。但主要的区别在于,JDO 仅考虑持久性问题(J2EE 数据层或者企业信息系l(EISQ层Q,?SDO 更具一般性,x的是不同 J2EE 层次间数据流的表C,比如表示层和业务层?/P>
有趣的是QSDO 可以l合 JDO 一起用,JDO 作ؓ数据源,SDO 来访问它Q这是 Data Transfer ObjectQ数据传输对象,DTOQ设计模式的具体q用。同PSDO 也可以结合实?EJB lg?Java Connector ArchitectureQJava q接器体pȝ构,JCAQ用,目的是提供统一的数据访问?/P>
SDO ?EMF
EMF 代表 Eclipse Modeling FrameworkQEclipse 建模框架Q。EMF Ҏ使用 Java 接口、XML Schema 或?UML cd定义的数据模型生成统一的元模型Q称?EcoreQ,可以元模型与框架结合在一起用,创徏高质量的模型实现。EMF 提供了持久性、一个有效的反射cd对象操纵 API 和一个变更通知框架。EMF q包括用来构?EMF 模型~辑器的一般的重用cR?/P>
EMF ?SDO 都可以处理数据表C。事实上QIBM ?SDO 参考实现就是一U?SDO ?EMF 实现Q后面我们还要用到该实现。还可以Ҏ UML 模型定义或?SDO 本nQ用 EMF 代码生成来创?SDO 实现的某些部分。SDO 实现基本上是 EMF 中的一层Q方面)Q它是作?EMF 目的一部分打包和提供的。关?EMF 的更多信息,请参?参考资?/A>?
SDO ?JAXB
JAXB 代表 Java API for XML Data BindingQXML 数据l定 Java APIQ。JAXB 1.0 ?2003 q?1 月由 JCP 发布。JCP 专家l已l制定了 2.0 版的初步草案。JAXB 是关?XML 数据l定的,也就是说Q将 XML 数据表示成内存中?Java 对象。作?Java 语言?XML l定框架QJAXB 可以节约解析和创?XML 文的时间。(事实上,通过它,您完全不需要和 XML 打交道。)JAXB 为您执行~组/序列化(Java ?XMLQ和解组/q行化(XML ?JavaQ?/P>
SDO 定义了自q Java l定框架Q但是走得还要远一些。JAXB 仅关?Java ?XML 的绑定,而绑定到 SDO 的不仅仅?XML 数据。如前所qͼSDO 提供了对不同cd数据的统一讉KQXML 仅是其中的一U数据类型。SDO q提供了静态和动?API *Q?JAXB 仅提供了静态绑定?
* 注意Q本文中CZ应用E序仅用了动?SDOQ虽?EMF 代码生成器也为数据对象的静态代码生成提供了完整的支持?/I>
SDO ?ADO .NET
ADO 代表 ActiveX Data ObjectsQActiveX 数据对象Q,但是?.NET 上下文中Q其含义已经发生了变化。ADO .NET 提供?.NET 框架下不同层ơ间的统一数据讉K机制?/P>
ADO .NET ?SDO h相同的动机,都是用来支持 XML 和分布在多个层上的应用程序。除了技术性的差异外,q两Ҏ术主要的不同在于QADO .NET 用于 Microsoft .NET q_Q是一U私有的技术;?SDO 用于 Java (J2EE) q_Q通过 Java Cq程实现标准化?/P>
SDO 的组成部?/SPAN>
q一节将介绍 SDO 的体pȝ构。我们将介绍l成框架的不同组成部分和它们之间的协作。首先要讨论的三个组成部分之一?SDO 的“概忉|”特征,API 中没有对应的接口?/P>
SDO 客户?/SPAN>
SDO 客户Z?SDO 框架处理数据。SDO 客户Z用的不是特定于技术的 API 和框Ӟ而是 SDO ~程模型?API。SDO 客户机处?SDO 数据图(参见 ?1Q,不需要了解所处理的数据是如何持久保存或者序列化的?
Data 中介服务
数据中介服务QDMSQ负责从数据源创建数据图、依据数据图的变化更新数据源。数据中介框架不属于 SDO 1.0 规范Q换句话_SDO 1.0 没有涉及具体?DMS。常见的 DMS ?JDBC DMS、实?EJB DMS ?XML DMS {?/P>
数据?/SPAN>
数据源不限于后端数据源(如持久存储数据库Q。数据源以自q格式保存数据。只?DMS 讉K数据源,SDO 应用E序不访问数据源。SDO 应用E序可能只用数据图中的数据对象?/P>
下面介绍的每个组件对应于 SDO ~程模型的一?Java 接口。SDO 参考实玎ͼ请参?参考资?/A>Q提供了q些接口Z EMF 的实现?
数据对象
数据对象?SDO 的基本组件。事实上Q它们是规范名称中的 服务数据对象。数据对象是l构化数据的 SDO 表示。数据对象是通用的,它们提供?DMS 创徏的结构化数据的公p图。比方说Q虽?JDBC DMS 需要知道持久性技术(比如关系数据库)Q以及如何配|和讉K数据QSDO 客户Z需要了解这些细节。数据对象在属性中保存它们的“数据”(E后q要讨论属性)。数据对象提供了易于使用的创建和删除ҎQ带有不同签名的 createDataObject()
?delete()
Q,获得自ncdQ实例类、名U、属性和名称I间Q的反射Ҏ。数据对象都链接在一P包含在数据图中?
数据?/SPAN>
数据图提供了数据对象树的容器。数据图?DMS 生成Q供 SDO 客户Z用。修改后Q数据图被回传给 DMS 更新数据源。SDO 客户机可以遍历数据图Q读取和修改数据图中的数据对象。SDO 是一U?无连接的体系机构Q因?SDO 客户Z DMS 和数据源没有q接Q所?SDO 客户机看到的只有数据图。此外,数据囑֏以包含表CZ同数据源中数据的对象。数据图包含一个根数据对象、与根关联的所有数据对象和变更摘要Qchange summaryQ参见本文后面的叙述Q。当在应用程序组Ӟ比如服务调用期间?Web 服务h者和提供者)之间q行传输、组件到 DMS 的传输(或者保存到盘Q的时候,数据图被序列化ؓ XML。SDO 规范提供了序列化?XML Schema。图 1 昄了一?SDO 数据图?
变更摘要
变更摘要包含在数据图中,表示?DMS q回的数据图的修攏V变更摘要最初是I的Q数据图刚返回客h的时候)Q随着数据囄变化逐渐填充。在后台更新ӞDMS 使用变更摘要修改应用于数据源。变更摘要提供了数据图中被修改的属性(包括原来的|、新增和删除的数据对象的列表Q从而 DMS 以递增方式高效地更新数据源。只有当变更摘要日志功能被激zLQ才会将信息d到数据图的变更摘要中。变更摘要提供了?DMS 打开和关闭日志功能的ҎQ后面的例子中还详l对其进行介l?/P>
属性、类型和序列
数据对象用一pd属性保存其内容。每个属性都有一个类型,该类型既可以是基本类型(?int
Q这L属性类型,也可以是通用数据cdQ如 Date
Q,如果引用的话Q还可以是其他数据对象类型。每个数据对象都为属性提供了讉K和设|方法(getter ?setterQ。这些访问器Ҏ有不同的重蝲版本Q可以通过传递属性名Q?String
Q、编P int
Q或者属性元对象本n来访问属性。String 讉K器还允许使用c?XPath 的语法访问属性。比如,可以对公司数据对象调?get("department[number=123]")
来访问编号ؓ 123的第一个部门。序列更加高U,可以保持不同U类的属?值对列表的顺序?
SDO 和示例安?/SPAN>
我们已经讲了很多的概念和理论Q现在要q行一些实际操作了。好消息是您马上p使用 SDOQ而且是免费的。这一节将介绍一?SDO CZ应用E序Q它在 SDO ?IBM 参考实Cq行Q这个参考实现是 Eclipse Modeling Framework (EMF) 的一部分。我们首先将说明如何安装 EMF 2.0.1Q包?SDOQ,然后介l如何设|本文提供的CZ应用E序?/P>
安装 EMF 2.0.1
如果已经安装?EMF 2.0.1Q或者知道怎么安装Q那么请跌q一节,直接阅读下一节?/P>
IBM SDO 1.0 实现?EMF 2.0.1 一h包。要使用 SDOQ则需要安?EMF 2.0.1 *。您可以按照 EMF 站点上的说明使用 Eclpise 更新理器,也可以按照下面的步骤操作?
*EMF 2.0.0 中也包含 SDO 1.0 的实现?
?EMF 主页中的“快速导航”部分可以找C载链接页面,选择下蝲“v2.x: EMF ?SDO”。安?EMF 之前一定要阅读安装要求。安?EMF 2.0.1 之前臛_要安装了 Eclipse 3.0.1 ?Java Development Kit (JDK) 1.4。一定要选择 EMF 2.0.1 发行版本。打包类型徏议选择“All”:emf-sdo-xsd-SDK-2.0.1.zipQ这P可以在一个文件中扑ֈ源代码、运行文件和文。如果愿意,q可以下?SDO 的最安装包“EMF & SDO RT”:emf-sdo-runtime-2.0.1.zip?
在解?Eclipse 的目录中解压 zip 文gQ压~包中的文gl织l构?eclipse/plugins/...Q。启?EclipseQ然后选择 Help>About the Eclipse PlatformQ检?EMF 是否安装成功。单?Plug-in Details按钮Q确?org.eclipse.emf.* 插g?2.0.1 层次上。有 6 个与 SDO 有关的插Ӟ
q行时只需要两个插Ӟ org.eclipse.emf.commonj.sdo
?org.eclipse.emf.ecore.sdo
Q如果选择仅安装运行时插gQ那么您只能看到q两个插件。这样就完成?EMF 的安装?
安装CZ SDO 应用E序
下一步是在工作区中添加本文所用的 SDO CZ应用E序Q步骤如下:
然后Q单L文顶端或底端?Code图标Q或者参?下蝲部分Q下?j-sdoSample.zipQƈ其解压~到 SDOSample 目录中(?Eclipse H口中选择 Import... >Zip fileQ。一定要保留文g夹结构ƈ覆盖原来的文Ӟq样Q就可以?j-sdoSample.zip 中的文g代替 SDOSample 目?
注意Q?/B>SDOSample 是作?Eclipse 插g目打包的,因此不需要自p|库依赖关系。但是,在本例中Q只包含 Java 代码Q如果在 CLASSPATH 中包?EMF ?SDO 库(JAR 文gQ,也可?SDOSample 作ؓ独立的应用程序运行?
环境讄应该与下面截屏图中的cM?/P>
现在开始用这个示?SDO 应用E序?/P>
一个简单的 SDO 应用E序
本文后面用的CZ应用E序从功能上说很有限Q但它可以帮助您更好地理?SDO。该应用E序包括两部分,分别攑֜两个包中Qdms ?client?/P>
SDO 1.0 没有规定标准 DMS API。因此我们ؓq个例子设计了自q DMS 接口Q它包含两个ҎQ如清单 1 所C?/P>清单 1. DMS 接口
|
客户机将实例?DMSQƈ调用 get()
Ҏ讉K特定的雇员:Big Boss、Wayne Blanchard ?Terence Shorter。它以用户友好的方式在控制台中打印这些雇员的信息Q然后更?Terence Shorter 及其雇员的部门信息。最后调?DMS ?update()
ҎQ传递更新的 Terence Shorter 数据图?
注意Qؓ了便于示范,我们没有实现数据源组Ӟ但在 DMS 中,有一些如何根据查询构建数据图的“硬~码”知识。图 3 昄?DMS 正在使用的雇员层ơ结构?/P>
图中可以看出QDMS 背后的虚拟公司有 4 个雇员,层次l构如下Q?/P>
q行CZ应用E序
叛_ SDOClient.javaQ然后选择 Run>Java applicationq行上述CZ应用E序Q结果如下:
|
现在我们来分析应用程序的各个l成部分是如何工作的?/P>
客户?/SPAN>
SDO 客户ZCZ DMSQƈ从中获得不同雇员的数据图。得到数据图后,通过根对象(使用 SDO 动?APIQ遍历和讉K数据对象Q如下所C:
|
客户用动?SDO 讉K?APIQ从数据对象中获得信息,q将其显C到控制CQ?/P>
|
我们已经看到客户机是如何获取信息Q读Q的Q但是如何写入信息呢Q更准确地说Q客h如何修改对象QSDO 客户Z般?DataObject
写访问器Ҏ更新数据对象。比如,下面的代码修改从雇员 Terence Shorter 获得的数据图Q?
|
注意Q客h没有调用日志Ҏ。DMS 负责Ҏ据图的变更摘要调?beginLogging()
?endLogging()
记录日志?
数据?/SPAN>
可以数据图的数据格式(模型Q看?DMS 与客h之间的抽象。客h期望?DMS 得到数据图,DMS 也知道如何创建数据读Q包括从后端数据源中d和更新数据)。如果熟?XML 或?Web 服务Q那么可以将数据图模型看作定义数据对?XML SchemaQXSDQ。数据图本nq?XML 实例文。事实上QXML Schema 也是定义 SDO 模型的一U方法?/P>
注意Q数据图及其模型L能够序列化ؓ XML。在 SDOClient.java 中将 debug
变量设ؓ true
Q就可以看到q行时在控制C昄的数据图的序列化版本Q与清单 3 cM?
|
在本例中Q数据图?Employee
数据对象Q以及变更摘要)l成?Employee
包含姓名、编受部门、职务、上司(理该雇员的另一位雇员)和下属(该雇员管理的其他雇员Q等属性。该例中Q雇员已l位于硬~码的数据源中时QDMS q回的数据图的格式L雇员的上司(如果有的话)、雇员及其直接下属(如果有的话)?
DMS 构徏数据?/SPAN>
SDO 1.0 没有规定 DMS APIQAPI 应该包含数据图模型本w的设计和创建。因为徏立对数据源的讉K要考虑很多U情况,设计数据图本w可以作为另一文章的主题?/P>
对这个例子,我们采?DMS 通过动?EMF API 定义的雇员模型。示例数据图没有 XSD q样的模型文。实际上Q因为对象是动态生成的Q所以这意味着没有生成 Employee
Java cR如果用静态方法,׃生成q样的类?
DMS 使用不同的数据访?APIQJDBC、SQL {)从不同数据源获取的信息。但是,一旦从后端Q该例中是硬~码的知识)索到信息QDMS p{而?EMF APIQeSet、eGetQ而非 SDO API 来创建数据对象的数据图。这U方法能得到较好的性能Q但~点是不能跨 SDO 实现UL?/P>
对于主要x性能Q同L DMS 设计也可使用 SDO API 实现。在q种情况下,DMS c( employeeClass
?employeeNameFeature
{)中缓冲的元对象,代?EMF cd EClass
?EAttribute
?EReference
{)Q成?commonj.sdo.Type
?commonj.sdo.Property
的类型。此外,如果性能不重要,那么可以方便C用基?String ?SDO APIQ如 setBoolean(String path, boolean value)
Q,因此不需要缓冲元对象。不q的是,q种解决Ҏ虽然更方便,但运行v来也更慢?
下面的代码片D说明了 SimpleEmployeeDataMediatorImpl.java ?Employee 模型的定义。但q些代码q没有构?SDO 对象Q构建的仅仅?SDO 对象的模型:
|
注意Q我们用?true
?employees EReference
调用 setContainment
Q因此每个雇员都“包含”他或她的下属。否则,嵌套的雇员就不会Q即被包含)在数据图中,变更摘要也只能包含根对象的修改,而不能包含其他雇员的修改?
建模 SDO
您可能想“很有趣Q但是这样只能得?EMF 对象而不?SDO 对象Q还有什么窍门吗Q”当然有Q而且很简单?Employee EClass
属于 employeePackage EPackage
Qƈ且包含下面的调用Q?
|
q行Ӟq个工厂创?DynamicEDataObjectImpl
cd的对象,该对象实C DataObject
接口Q即它是一?SDO 数据对象Q,而不是默认的 DynamicEObjectImpl
接口Qƈ且可以智能地创徏普通的 EMF 对象。SDO ?EMF 对象之间的关pd很清楚了QSDO 对象是同时实现?SDO DataObject
接口?EMF 对象。事实上Q这些附加方法的实现是委z核心 EMF Ҏ实现的?
创徏 SDO 实例
现在Q已l拥有了我们的数据对象,可以徏?Employee
的实例ƈ讄不同的属性了。如前所qͼ我们?EMF API 来最大程度地提高性能?
|
可以使用“employees”引用把雇员“链接”在一P比如Q?/P>
|
一旦创Z数据对象Q还需要将其连接到数据图中。我们首先要调用数据囄 setRootObject()
ҎQ传递希望用作根的数据对象,q里使用 Employee The Boss
?
|
l箋讨论数据图之前,要先开始记录日志。如果希望?SDOQ那么在改动数据图之前,要先调用其变更摘要的 beginLogging()
Ҏ。基本的原理是清除以前的变化,开始监听新的修攏V?
|
DMS 的另一Q务(按照 EmployeeDataMediator
接口的定义)是根?SDO 客户机提供的数据图更新后端数据源?
DMSQ更新数据源
DMS 应该使用 SDO 的强大特性更新后端数据源Q具体地_是要用其变更摘要。用数据图的变更摘要有许多不同的方法。该例中Q我们将考察变更摘要树中引用的所有数据对象,q从中获得新的数据对象?/P>清单 4. DMS Ҏ数据图更新后端数据源
|
该例中根本没有后端更新。但在实际应用时Q后端更新应该在q个Ҏ中完成?/P>
DMS 首先要对数据囄更新摘要调用 endLogging()
Q从客户机取回数据图Q以便进行后端更新。这样将关闭变更记录Q从而提供自 beginLogging()
调用以来Q通常在创Z后调用)Ҏ据图所做修改的摘要。这U格式支?DMS 高效、递增地更新后端数据源。变更摘要中的修改分ZU类型:
注意Q我们用标准的 SDO API 查数据图的变化,虽然也可以?EMF ChangeDescription APIQ而不?SDO ?ChangeSummaryQ。该例中仅仅更新单的属性|Ҏ能的媄响不是很明显。但在其他情况下Q比方说要更新大量的属性,使用 EMF API 可以显著地提高性能。比如,假设要从数百个雇员的列表中删除一个雇员。在q种情况下,ChangeSummary 只能提供对原有数百个雇员列表中的原有值的讉K??EMF ?ChangeDescription 接口q可以提供更具体的信息,如“删除某个烦引位|的雇员”,q就有用得多?/P>
q要注意的是Q该变更摘要中只修改了一个对象,没有删除或者添加对象。如果?SDO 实现从数据图中删除对象,q要注意cd?objectsToAttach 的元素。该名称实际上是对象删除?EMF ChangeDescription 名。这些元素是那些已经删除但是在回滚时需要放回图中的数据对象Q这是变更?EMF 视图。总而言之, objectsToAttach == deleted objectsQ删除的对象Q?/CODE> ?
调试应用E序
如果在示例应用程序中?debug
变量设ؓ true
Q那么就可以执行以下调用Q查看数据图的序列化版本?
|
q可以?Eclipse 调试环境。比如,我们?SDOClient.java W?100 行设|一个断点,q调?SDOClient
Q像?Java 应用E序中那P。然后,在调试窗口中可以看到内存中的数据图Q在 Variables 下)和它的数据对象(Boss、Terrence Shorter {)Q如?4 所C?
q可以用q种Ҏ查看变更摘要Q如?5 所C?/P>
上面的截屏图看v来很复杂Q现在看来用处也不大Q但是当您调试自q SDO 应用E序q查看数据对象和变更摘要的内ҎQ就会用到它?/P>
l束?/SPAN>
本文要描qC SDO 及其功能。我们通过一个示例应用程序说明了 SDO 的一些功能。更多参考信息,请参?Eclipse 帮助pȝ下的 SDO API 文。该规范仍在发展和改q之中。比如,SDO 1.0 ?SDO 的客h斚wQ而没有指定一?DMS API。SDO 目前正通过 JCP 实现标准化,请关注有关的q展情况。因?SDO 非常灉|Q设?SDO 应用E序旉要做很多决策。这些决{将影响E序的重用性和性能。因此,在编码之前,应该认真考虑应用模式和应用程序数据的特征?/P>
![]() |
Name | ![]() |
Size | ![]() |
Download method | ![]() | ||||||
j-sdoSample.zip | ![]() |
![]() |
FTP | ![]() | |||||||
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() ![]() |
作者简?/SPAN> Bertrand Portier ?IBM 的Y件开发h员,他是?Eclipse.org 上开?SDO 参考实现的 EMF 开发小l的主要成员。他拥有使用 J2EE 的丰富经验,曄参与q?IBM 产品?Web 服务领域的开发,q帮?IBM 客户开发自q分布式应用程序? |
|
得到Appliaction workspace, Platform.asLocalURL(PRODUCT_BUNDLE.getEntry("")).getPath()).getAbsolutePath();
得到runtimeworkspace, Platform.getInstanceLocation().getURL().getPath();
通过EditorInput来得到工E的l对路径Q?BR>
((IFileEditorInput)input).getFile().getLocation().makeAbsolute().toFile().getAbsoluteFile().getParentFile();
通过父EditPart得到~辑器的ҎQGEFQ:
IEditorPart editor = ((DefaultEditDomain)(parent.getViewer().getEditDomain())).getEditorPart();