So what happened here? Why Eclipse know how to process your popup menu contribution? How to add a pretty new functionality to Eclipse, which can't find or defined by Eclipse's existing extension-point? The answer is: contribute a extension-point for Eclipse by yourself.
Here I will use a example to explain how to define a extension-point by yourself, suppose I want to write a view that will show services status which deploy in a container like tomcat, spring, websphere etc., and customer can add any unknown containers support by implement my new extension-point for this view.
1. The requirements
I want to get service from container, also I need support unknown container type, so a client will be needed, i.e. I can user that client to get what I want to show in my view. So here I will define a client extension-point and this client will follow the interface contract below:
- public interface IClient {
- public void setHost(String host);
- public void setPort(int port);
- public void createClient();
- public List<IService> listServices();
- }
The three methods at beginning will set connection information for client and create a client instance, then listServices() will get service back
2. Define client extension-point
You can use PDE extension-point schema editor do this, here's my client schema:
- <?xml version='1.0' encoding='UTF-8'?>
- <!-- Schema file written by PDE -->
- <schema targetNamespace="com.example.services">
- <annotation>
- <appInfo>
- <meta.schema plugin="com.example.services" id="clients" name="Clients"/>
- </appInfo>
- <documentation>
- this extension-point will be used to connect different container
- </documentation>
- </annotation>
- <element name="extension">
- <complexType>
- <sequence minOccurs="1" maxOccurs="unbounded">
- <element ref="client"/>
- </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="client">
- <complexType>
- <attribute name="id" type="string" use="required">
- <annotation>
- <documentation>
- </documentation>
- </annotation>
- </attribute>
- <attribute name="name" type="string" use="required">
- <annotation>
- <documentation>
- </documentation>
- </annotation>
- </attribute>
- <attribute name="clientType" type="string" use="required">
- <annotation>
- <documentation>
- </documentation>
- </annotation>
- </attribute>
- <attribute name="class" type="string" use="required">
- <annotation>
- <documentation>
- </documentation>
- <appInfo>
- <meta.attribute kind="java" basedOn="com.example.services.client.IClient"/>
- </appInfo>
- </annotation>
- </attribute>
- </complexType>
- </element>
- <annotation>
- <appInfo>
- <meta.section type="since"/>
- </appInfo>
- <documentation>
- 2007/09
- </documentation>
- </annotation>
- <annotation>
- <appInfo>
- <meta.section type="examples"/>
- </appInfo>
- <documentation>
- <pre>
- <extension
- point="com.example.services.clients">
- <client
- class="com.example.services.TomcatClient"
- clientType="tomcat"
- id="com.example.services.TomcatClient"
- name="Tomcat Client"/>
- </extension>
- </pre>
- </documentation>
- </annotation>
- <annotation>
- <appInfo>
- <meta.section type="apiInfo"/>
- </appInfo>
- <documentation>
- extension of this extension-point must implement <samp>com.example.services.client.IClient</samp>
- </documentation>
- </annotation>
- <annotation>
- <appInfo>
- <meta.section type="implementation"/>
- </appInfo>
- <documentation>
- see com.example.services plugin for a implementation example
- </documentation>
- </annotation>
- <annotation>
- <appInfo>
- <meta.section type="copyright"/>
- </appInfo>
- <documentation>
- alexgreenbar
- </documentation>
- </annotation>
- </schema>
3. Extension-point handle classes
When my view need get services status back, I need load all contributed extension, and instance client which know how to get service status back, here's code:
- //describe every client contribution
- public class ClientsEntry {
- private final static String ATTR_TYPE = "clientType";
- private final static String ATTR_CLAZZ = "class";
- private IConfigurationElement element;
- private String type;
- public ClientsEntry(IConfigurationElement aElement) {
- element = aElement;
- type = element.getAttribute(ATTR_TYPE);
- }
- public String getType() {
- return type;
- }
- public IClient createClient() throws CoreException {
- return (IClient)element.createExecutableExtension(ATTR_CLAZZ);
- }
- }
- //ClientsRegistry manage all client contribution, use singleton pattern
- public class ClientsRegistry {
- private final static Logger LOG = Logger.getLogger(ClientsRegistry.class.getName());
- private final static String EXTENSION_POINT_ID = "com.example.services.clients";
- private final static ClientsRegistry INSTANCE = new ClientsRegistry();
- private List<ClientsEntry> entries = new ArrayList<ClientsEntry>();
- private ClientsRegistry() {
- //
- }
- public static ClientsRegistry getInstance() {
- return INSTANCE;
- }
- private void load(){
- entries.clear();
- IExtensionRegistry registry = Platform.getExtensionRegistry();
- IExtensionPoint point = registry.getExtensionPoint(EXTENSION_POINT_ID);
- for (IExtension extension : point.getExtensions()){
- for (IConfigurationElement element : extension.getConfigurationElements()){
- entries.add(new ClientsEntry(element));
- }
- }
- }
- public List<ClientsEntry> getEntries() {
- load();
- return entries;
- }
- public IClient getClient(String type) {
- IClient client = null;
- load();
- for (ClientsEntry entry : entries) {
- if (entry.getType().equalsIgnoreCase(type)) {
- try {
- client = entry.createClient();
- } catch (CoreException e) {
- LOG.log(Level.FINE, "can't instance client extension: ", e);
- client = null;
- continue;
- }
- break;
- }
- }
- return client;
- }
- }
4. A example client extension
- <extension
- point="com.example.services.clients">
- <client
- class="com.example.services.TomcatClient"
- clientType="tomcat"
- id="com.example.services.TomcatClient"
- name="Tomcat Client"/>
- </extension>
5. Use client extension
In the view code:
- String newClientType = "tomcat"
- IClient client = ClientRegistry.getInstance().getClient(newClientType);
- client.setHost("localhost");
- client.setPort(8080);
- client.createClient();
- List<IService> allServices = client.listServices();
6. Summary
So write a extension-point is not so hard? It's pretty easy actually! Could you imagine all the powerful functionalities of Eclipse are based on this extension mechanism?
- ClientsEntry, ClientsRegistry can be reused, they are similar with code in Eclipse itself that process extension-point
- the most important thing is design your extension-point API contract and select a suitable opportunity to load your extension, apply lazy loading when possible
安徽新华电脑学校专业职业规划师为你提供更多帮助【在线咨询】