修饰工作
给facet在选择列表中添加图标
格式如下:
xml 代码
- <extension point="org.eclipse.wst.common.project.facet.ui.images">
- <image facet="{string}" path="{string}"/> (0 or more)
- <image category="{string}" path="{string}"/> (0 or more)
- extension>
设置如下:
xml 代码
- <extension point="org.eclipse.wst.common.project.facet.ui.images">
- <image facet="formgen.core" path="icons/formgen-core.gif"/>
- <image facet="formgen.ext" path="icons/formgen-ext.gif"/>
- <image category="formgen.category" path="icons/formgen-cat.gif"/>
- extension>
效果如图
添加向导页
有时候我们可能需要根据用户的输入来执行facet, 通过添加wizard page来接收用户的输入, 用户在facet选择列表页做出选择之后,将出现我们添加的wizard Page
下面通过给我们的servlet指定url pattern的例子来进行说明
plugin.xml设置格式如下:
xml 代码
- <extension point="org.eclipse.wst.common.project.facet.core.facets">
- <action>
- <config-factory class="class:org.eclipse.wst.common.project.facet.core.IActionConfigFactory"/>
- action>
- extension>
-
- <extension point="org.eclipse.wst.common.project.facet.ui.wizardPages">
- <wizard-pages action="{string}"> (0 or more)
- <page class="{class:org.eclipse.wst.common.project.facet.ui.IFacetWizardPage}"/> (1 or more)
- wizard-pages>
- extension>
这里需要说明的是为了让我们定制的wizard page和action delegate之间进行通信, 需要使用一个javabean或者是map来封装wizard page中输入的数据, 而且必须在action配置中提供一个action factory,该对象将由factory创建, wizard page填充数据, action delegate负责从该对象读取数据
除外,wizard page将通过指定的action id来引用action, 这也是我们前面推荐指定action id而不是系统生成的原因
配置如下:
xml 代码
- <extension point="org.eclipse.wst.common.project.facet.core.facets">
- <project-facet-version facet="formgen.core" version="1.0">
- <action type="INSTALL" id="formgen.core.install">
- <config-factory class="com.formgen.eclipse.FormGenCoreFacetInstallConfig$Factory"/>
- action>
- project-facet-version>
- extension>
-
- <extension point="org.eclipse.wst.common.project.facet.ui.wizardPages">
- <wizard-pages action="formgen.core.install">
- <page class="com.formgen.eclipse.FormGenCoreFacetInstallPage"/>
- wizard-pages>
- extension>
代码如下:
java 代码
- package com.formgen.eclipse;
-
- import org.eclipse.wst.common.project.facet.core.IActionConfigFactory;
-
- public final class FormGenCoreFacetInstallConfig
- {
- private String urlPattern = "*.form";
-
- public String getUrlPattern()
- {
- return this.urlPattern;
- }
-
- public void setUrlPattern( final String urlPattern )
- {
- this.urlPattern = urlPattern;
- }
-
- public static final class Factory implements IActionConfigFactory
- {
- public Object create()
- {
- return new FormGenCoreFacetInstallConfig();
- }
- }
- }
-
java 代码
- package com.formgen.eclipse;
-
- import org.eclipse.swt.SWT;
- import org.eclipse.swt.layout.GridData;
- import org.eclipse.swt.layout.GridLayout;
- import org.eclipse.swt.widgets.Composite;
- import org.eclipse.swt.widgets.Label;
- import org.eclipse.swt.widgets.Text;
- import org.eclipse.wst.common.project.facet.ui.AbstractFacetWizardPage;
-
- public final class FormGenCoreFacetInstallPage extends AbstractFacetWizardPage
- {
- private FormGenCoreFacetInstallConfig config;
- private Text urlPatternTextField;
-
- public FormGenCoreFacetInstallPage()
- {
- super( "formgen.core.facet.install.page" );
-
- setTitle( "FormGen Core" );
- setDescription( "Configure the FormGen servlet." );
- }
-
- public void createControl( final Composite parent )
- {
- final Composite composite = new Composite( parent, SWT.NONE );
- composite.setLayout( new GridLayout( 1, false ) );
-
- final Label label = new Label( composite, SWT.NONE );
- label.setLayoutData( gdhfill() );
- label.setText( "URL Pattern:" );
-
- this.urlPatternTextField = new Text( composite, SWT.BORDER );
- this.urlPatternTextField.setLayoutData( gdhfill() );
- this.urlPatternTextField.setText( this.config.getUrlPattern() );
-
- setControl( composite );
- }
-
- public void setConfig( final Object config )
- {
- this.config = (FormGenCoreFacetInstallConfig) config;
- }
-
- public void transferStateToConfig()
- {
- this.config.setUrlPattern( this.urlPatternTextField.getText() );
- }
-
- private static GridData gdhfill()
- {
- return new GridData( GridData.FILL_HORIZONTAL );
- }
- }
-
java 代码
- package com.formgen.eclipse;
-
- import org.eclipse.core.resources.IFolder;
- import org.eclipse.core.resources.IProject;
- import org.eclipse.core.runtime.CoreException;
- import org.eclipse.core.runtime.IProgressMonitor;
- import org.eclipse.core.runtime.Path;
- import org.eclipse.wst.common.project.facet.core.IDelegate;
- import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;
-
- public final class FormGenCoreFacetInstallDelegate implements IDelegate
- {
- public void execute( final IProject pj,
- final IProjectFacetVersion fv,
- final Object config,
- final IProgressMonitor monitor )
-
- throws CoreException
-
- {
- monitor.beginTask( "", 2 );
-
- try
- {
- final FormGenCoreFacetInstallConfig cfg
- = (FormGenCoreFacetInstallConfig) config;
-
- final IFolder webInfLib = Utils.getWebInfLibDir( pj );
-
- Utils.copyFromPlugin( new Path( "libs/formgen-core.jar" ),
- webInfLib.getFile( "formgen-core.jar" ) );
-
- monitor.worked( 1 );
-
- Utils.registerFormGenServlet( pj, cfg.getUrlPattern() );
-
- monitor.worked( 1 );
- }
- finally
- {
- monitor.done();
- }
- }
- }
-
效果如图
定义Preset
为了将创建某个工程所需要的facet集中在一个用一个名字代替,这就需要使用preset(或称configuration),其扩展点格式如下:
xml 代码
- <extension point="org.eclipse.wst.common.project.facet.core.facets">
- <preset id="{string}">
- <label>{string}</label>
- <description>{string}</description> (optional)
- <facet id="{string}" version="{string}"/> (1 or more)
- </preset>
- </extension>
为了让preset能应用于指定的facet project, preset必须包含所有的fixed facet, 所谓的fixed facet指的是那些要创建的工程所必须的而不能删除的facet.
设置如下:
xml 代码
- <extension point="org.eclipse.wst.common.project.facet.core.facets">
- <preset id="formgen.preset">
- <label>FormGen Web Project</label>
- <description>Creates a web project with FormGen functionality.</description>
- <facet id="jst.java" version="5.0"/>
- <facet id="jst.web" version="2.2"/>
- <facet id="formgen.core" version="1.0"/>
- <facet id="formgen.ext" version="1.0"/>
- </preset>
- </extension>
效果如图
指定runtime映射
在创建project的时候,有时候需要指定项目依赖的runtime,我们也可以通过扩展点来检查当前的facet所需要的runtime是否指定.
配置格式如下:
xml 代码
- <extension point="org.eclipse.wst.common.project.facet.core.runtimes">
- <supported> (0 or more)
- <runtime-component any="{boolean}"/> (optional)
- <runtime-component id="{string}"/ version="{version.expr}"/> (0 or more)
- <facet id="{string}"/ version="{version.expr}"/> (1 or more)
- </supported>
- </extension>
下面是不依赖其他组件的配置:
xml 代码
- <extension point="org.eclipse.wst.common.project.facet.core.runtimes">
- <supported>
- <runtime-component any="true"/>
- <facet id="formgen.core"/>
- <facet id="formgen.ext"/>
- </supported>
- </extension>
下面是依赖tomcat的配置
xml 代码
- <extension point="org.eclipse.wst.common.project.facet.core.runtimes">
- <supported>
- <runtime-component id="org.eclipse.jst.server.tomcat" version="[5.0"/>
- <facet id="formgen.core"/>
- <facet id="formgen.ext"/>
- </supported>
- </extension>
总结
通过上面的步骤, 我们创建了一个完整的project facet, 这里面包括指定约束, 实现action, 对facet分组, 创建wizard page. 更多的信息可看下面的参考附录
附录A 定制Version Comparetor
就是对版本进行比较的策略进行定制, 如果要使用自己的版本比较方式, 那么可以通过扩展点来处理,格式如下:
xml 代码
- <extension point="org.eclipse.wst.common.project.facet.core.facets">
- <project-facet>
- <version-comparator class="{class:java.util.Comparator<String>}"/>
- </project-facet>
- </extension>
可以直接从接口从头实现,也可以继承org.eclipse.wst.common.project.facet.core.DefaultVersionComparator来进行定制
代码如下:
java 代码
-
-
-
-
-
-
-
-
- protected String getSeparators();
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- protected Comparable parse( final String version,
- final String segment,
- final int position )
-
- throws VersionFormatException;
附录B Version Expression
为了一次指定多个版本,就需要使用版本表达式(version expression), 在很多地方我都用到了版本表达式, 版本表达式如果有多个,则使用逗号分隔,这里的逗号表示或的意思, 范围通过括号加破折号来制定,如[x-z), 中括号表示包含, 小括号表示不包含
下面是一些例子:
1.2
1.2,1.5,3.2
[1.2-3.2]
[3.7-5.0)
[3.7
5.0)
1.2,[3.0-4.5),[7.3
附录C Event Handler
project fact可以为某些事件注册listener, 这些时间包括:
PRE_INSTALL
POST_INSTALL
PRE_UNINSTALL
POST_UNINSTALL
PRE_VERSION_CHANGE
POST_VERSION_CHANGE
RUNTIME_CHANGED
事件处理器的声明和action的声明非常类似,但是他们也有一些区别,主要体现在:
与action不同, 事件处理器无法由用户直接触发,因此无法将事件处理器与wizard page关联,也无法为其提供封装数据的配置对象
可以给一个事件设置多个事件处理器,但是他们的调用顺序是不确定的
事件处理器的配置格式如下:
xml 代码
- <extension point="org.eclipse.wst.common.project.facet.core.facets">
- <event-handler facet="{string}" version="{version.expr}" type="{event.type}">
- <delegate class="{class:org.eclipse.wst.common.project.facet.core.IDelegate}"/>
- </action>
- </extension>
与action的配置很类似,也实现了IDelegate接口, 而且event-handler也可以嵌入到project-facet-version元素内部,此时的facet和version属性将被忽略.
PRE_* and POST_* 事件处理器用来取得配置对象,然后传递给IDelegate的execute方法使用, RUNTIME_CHANGED 事件处理器是用来取得IRuntimeChangedEvent实例
java 代码
- package org.eclipse.wst.common.project.facet.core;
-
- import org.eclipse.wst.common.project.facet.core.runtime.IRuntime;
-
-
-
-
-
- public interface IRuntimeChangedEvent
- {
-
-
-
-
-
-
- IRuntime getOldRuntime();
-
-
-
-
-
-
-
- IRuntime getNewRuntime();
- }
-
附录D Property Tester
Property Tester是用来被org.eclipse.core.expressions 包中的扩展点测试使用的,它常用来决定某些菜单或者属性页选项是否可用.属性名为org.eclipse.wst.common.project.facet.core.projectFacet,值为facet id或者facet id 加冒号再加版本表达式的组合
下面的这个例子用来控制project的属性页是否可用
xml 代码
- <extension point="org.eclipse.ui.propertyPages">
- <page
- adaptable="true"
- objectClass="org.eclipse.core.resources.IProject"
- name="FormGen Properties"
- class="com.formgen.eclipse.FormGenPropertiesPage"
- id="org.eclipse.jst.j2ee.internal.J2EEDependenciesPage">
- <enabledWhen>
- <test
- forcePluginActivation="true"
- property="org.eclipse.wst.common.project.facet.core.projectFacet"
- value="formgen.core"/>
- </enabledWhen>
- </page>
- </extension>
附录E Wizard Content
有时候我们可能根据其他facet所对应的wizard page的用户输入来调整action的行为, 而IWizardContet接口就是为该目的而设计的, wizard page的setWizardContext方法被调用的时候会取得该接口的handler, 如果你的代码对IWziardContenxt造成依赖,可能需要注意以下事项:
1.fact需要的内容可能在执行前已经被install了, 此时在wizard context中将无法找到要install的配置,所以在需要做一些判断
2.如果某些情况下wizard page不被调用的话,要给配置对象设置默认值
下面是IWizardContext接口的代码:
java 代码
- package org.eclipse.wst.common.project.facet.ui;
-
- import java.util.Set;
-
- import org.eclipse.core.runtime.CoreException;
- import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;
- import org.eclipse.wst.common.project.facet.core.IFacetedProject.Action;
- import org.eclipse.wst.common.project.facet.core.IFacetedProject.Action.Type;
-
-
-
-
-
-
- public interface IWizardContext
- {
-
-
-
-
-
-
-
-
- String getProjectName();
-
-
-
-
-
-
-
-
-
-
-