|
| 1 | +--- |
| 2 | +author: "Phong Nguyen" |
| 3 | +title: "Java OSGi Service" |
| 4 | +date: "2025-02-27" |
| 5 | +description: "Java: Eclipse Extensions and Extension Points" |
| 6 | +tags: ["java","eclipse"] #tags search |
| 7 | +FAcategories: ["syntax"] #The category of the post, similar to tags but usually for broader classification. |
| 8 | +FAseries: ["Themes Guide"] #indicates that this post is part of a series of related posts |
| 9 | +aliases: ["migrate-from-jekyl"] #Alternative URLs or paths that can be used to access this post, useful for redirects from old posts or similar content. |
| 10 | +ShowToc: true # Determines whether to display the Table of Contents (TOC) for the post. |
| 11 | +TocOpen: true # Controls whether the TOC is expanded when the post is loaded. |
| 12 | +weight: 12 # The order in which the post appears in a list of posts. Lower numbers make the post appear earlier. |
| 13 | +--- |
| 14 | +Explain how to use the OSGi Service |
| 15 | +[Refer1](https://www.vogella.com/tutorials/EclipseExtensionPoint/article.html) |
| 16 | +[Refer2](https://help.eclipse.org/latest/index.jsp?topic=%2Forg.eclipse.pde.doc.user%2Fguide%2Ftools%2Feditors%2Fmanifest_editor%2Fextension_points.htm) |
| 17 | +[Refer3](https://vogella.com/blog/getting-started-with-osgi-declarative-services-2024/)<br> |
| 18 | +## 1. Introduction |
| 19 | +- **Extensions** are the central mechanism for contribute behavior to the platform. We used it to contribute functionality to a certain type of API. |
| 20 | +- **Extension points** define new functions points for the platform that other plug-ins can plug into. |
| 21 | +- **E.g.** When you want to create modular that can be added or removed at runtime, you can use the OSGi service. |
| 22 | +- These extensions and extension points are defined via the `plugin.xml` file. |
| 23 | + |
| 24 | +<br> |
| 25 | + |
| 26 | + |
| 27 | +## 2. Using Extension points/ Extensions |
| 28 | + |
| 29 | +## 2.1. Create an EXTENSION POINT |
| 30 | +- A plugin which declares an **extension point** must declare the extension point in its plugin.xml. |
| 31 | +- It will contain code to evaluate the **extensions**. |
| 32 | +```xml |
| 33 | +<?xml version="1.0" encoding="UTF-8"?> |
| 34 | +<?eclipse version="3.4"?> |
| 35 | +<plugin> |
| 36 | + <extension-point id="com.extensionpoint.greeters" |
| 37 | + name="Greeters" |
| 38 | + schema="schema/com.extensionpoint.greeters.exsd" /> |
| 39 | +</plugin> |
| 40 | +``` |
| 41 | +- It has three attributes: |
| 42 | + - `id`: a required attr, simple name id |
| 43 | + - `name`: a required attr, sime name string |
| 44 | + - `schema`: optional attr, describe |
| 45 | + |
| 46 | +- **Examples**: Create a plugin named `com.extensionpoint.definition` contained the a extension point. |
| 47 | +```XML |
| 48 | +//MANIFEST |
| 49 | +Manifest-Version: 1.0 |
| 50 | +Bundle-ManifestVersion: 2 |
| 51 | +Bundle-Name: A Plugin for the Extension Point Definition |
| 52 | +Bundle-SymbolicName: com.extensionpoint.definition;singleton:=true |
| 53 | +Bundle-Version: 1.0.0.qualifier |
| 54 | +Export-Package: com.extensionpoint.definition |
| 55 | +Bundle-Vendor: Phong |
| 56 | +Automatic-Module-Name: com.extensionpoint.definition |
| 57 | +Bundle-RequiredExecutionEnvironment: JavaSE-21 |
| 58 | +Import-Package: org.eclipse.core.runtime;version="[3.7.0,4.0.0)", |
| 59 | + org.eclipse.e4.core.di.annotations;version="[1.6.0,2.0.0)" |
| 60 | +``` |
| 61 | + |
| 62 | +```XML |
| 63 | +// plugin.xml |
| 64 | +<?xml version="1.0" encoding="UTF-8"?> |
| 65 | +<?eclipse version="3.4"?> |
| 66 | +<plugin> |
| 67 | + <extension-point id="com.vogella.extensionpoint.definition.greeter" name="Greeter (Extension Point Name)" schema="schema/com.vogella.extensionpoint.definition.greeter.exsd"/> |
| 68 | + |
| 69 | +</plugin> |
| 70 | +``` |
| 71 | +// exsd |
| 72 | +<?xml version='1.0' encoding='UTF-8'?> |
| 73 | +<!-- Schema file written by PDE --> |
| 74 | +<schema targetNamespace="com.vogella.extensionpoint.definition" xmlns="http://www.w3.org/2001/XMLSchema"> |
| 75 | +<annotation> |
| 76 | + <appinfo> |
| 77 | + <meta.schema plugin="com.vogella.extensionpoint.definition" id="com.vogella.extensionpoint.definition.greeter.id" name="Greeter (Extensio Point Name)"/> |
| 78 | + </appinfo> |
| 79 | + <documentation> |
| 80 | + [Enter description of this extension point.] |
| 81 | + </documentation> |
| 82 | + </annotation> |
| 83 | + |
| 84 | + <element name="extension"> |
| 85 | + <annotation> |
| 86 | + <appinfo> |
| 87 | + <meta.element /> |
| 88 | + </appinfo> |
| 89 | + </annotation> |
| 90 | + <complexType> |
| 91 | + <choice minOccurs="1" maxOccurs="unbounded"> |
| 92 | + <element ref="client"/> |
| 93 | + </choice> |
| 94 | + <attribute name="point" type="string" use="required"> |
| 95 | + <annotation> |
| 96 | + <documentation> |
| 97 | + |
| 98 | + </documentation> |
| 99 | + </annotation> |
| 100 | + </attribute> |
| 101 | + <attribute name="id" type="string"> |
| 102 | + <annotation> |
| 103 | + <documentation> |
| 104 | + |
| 105 | + </documentation> |
| 106 | + </annotation> |
| 107 | + </attribute> |
| 108 | + <attribute name="name" type="string"> |
| 109 | + <annotation> |
| 110 | + <documentation> |
| 111 | + |
| 112 | + </documentation> |
| 113 | + <appinfo> |
| 114 | + <meta.attribute translatable="true"/> |
| 115 | + </appinfo> |
| 116 | + </annotation> |
| 117 | + </attribute> |
| 118 | + </complexType> |
| 119 | + </element> |
| 120 | + |
| 121 | + <element name="client"> |
| 122 | + <complexType> |
| 123 | + <attribute name="class" type="string"> |
| 124 | + <annotation> |
| 125 | + <documentation> |
| 126 | + |
| 127 | + </documentation> |
| 128 | + <appinfo> |
| 129 | + <meta.attribute kind="java"/> |
| 130 | + </appinfo> |
| 131 | + </annotation> |
| 132 | + </attribute> |
| 133 | + </complexType> |
| 134 | + </element> |
| 135 | + |
| 136 | + <annotation> |
| 137 | + <appinfo> |
| 138 | + <meta.section type="since"/> |
| 139 | + </appinfo> |
| 140 | + <documentation> |
| 141 | + [Enter the first release in which this extension point appears.] |
| 142 | + </documentation> |
| 143 | + </annotation> |
| 144 | + |
| 145 | + <annotation> |
| 146 | + <appinfo> |
| 147 | + <meta.section type="examples"/> |
| 148 | + </appinfo> |
| 149 | + <documentation> |
| 150 | + [Enter extension point usage example here.] |
| 151 | + </documentation> |
| 152 | + </annotation> |
| 153 | + |
| 154 | + <annotation> |
| 155 | + <appinfo> |
| 156 | + <meta.section type="apiinfo"/> |
| 157 | + </appinfo> |
| 158 | + <documentation> |
| 159 | + [Enter API information here.] |
| 160 | + </documentation> |
| 161 | + </annotation> |
| 162 | + |
| 163 | + <annotation> |
| 164 | + <appinfo> |
| 165 | + <meta.section type="implementation"/> |
| 166 | + </appinfo> |
| 167 | + <documentation> |
| 168 | + [Enter information about supplied implementation of this extension point.] |
| 169 | + </documentation> |
| 170 | + </annotation> |
| 171 | + |
| 172 | + |
| 173 | +</schema> |
| 174 | + |
| 175 | +```xml |
| 176 | + |
| 177 | +``` |
| 178 | + |
| 179 | +```java |
| 180 | +// Evaluation class |
| 181 | +package com.extensionpoint.definition; |
| 182 | + |
| 183 | +import org.eclipse.core.runtime.CoreException; |
| 184 | +import org.eclipse.core.runtime.IConfigurationElement; |
| 185 | +import org.eclipse.core.runtime.IExtensionRegistry; |
| 186 | +import org.eclipse.core.runtime.ISafeRunnable; |
| 187 | +import org.eclipse.core.runtime.SafeRunner; |
| 188 | +import org.eclipse.e4.core.di.annotations.Execute; |
| 189 | + |
| 190 | +public class EvaluateContributionsHandler { |
| 191 | + private static final String IGREETER_ID = |
| 192 | + "com.extensionpoint.definition.greeter"; |
| 193 | + |
| 194 | + @Execute |
| 195 | + public void execute(IExtensionRegistry registry) { |
| 196 | + IConfigurationElement[] config = |
| 197 | + registry.getConfigurationElementsFor(IGREETER_ID); |
| 198 | + try { |
| 199 | + for (IConfigurationElement e : config) { |
| 200 | + System.out.println("Evaluating extension"); |
| 201 | + final Object o = |
| 202 | + e.createExecutableExtension("class"); |
| 203 | + if (o instanceof IGreeter) { |
| 204 | + executeExtension(o); |
| 205 | + } |
| 206 | + } |
| 207 | + } catch (CoreException ex) { |
| 208 | + System.out.println(ex.getMessage()); |
| 209 | + } |
| 210 | + } |
| 211 | + |
| 212 | + private void executeExtension(final Object o) { |
| 213 | + ISafeRunnable runnable = new ISafeRunnable() { |
| 214 | + @Override |
| 215 | + public void handleException(Throwable e) { |
| 216 | + System.out.println("Exception in client"); |
| 217 | + } |
| 218 | + |
| 219 | + @Override |
| 220 | + public void run() throws Exception { |
| 221 | + ((IGreeter) o).greet(); |
| 222 | + } |
| 223 | + }; |
| 224 | + SafeRunner.run(runnable); |
| 225 | + } |
| 226 | +} |
| 227 | +``` |
| 228 | + |
| 229 | +```java |
| 230 | +// Attribute class |
| 231 | +package com.vogella.extensionpoint.definition; |
| 232 | + |
| 233 | +public interface IGreeter { |
| 234 | + void greet(); |
| 235 | +} |
| 236 | + |
| 237 | +``` |
| 238 | +<br> |
| 239 | + |
| 240 | +## 2.2. Create/adding EXTENSIONS to EXTENSION POINTS |
| 241 | +- **Examples**: Create a plugin named `com.extension.contribution` contained the a extension. |
| 242 | +```XML |
| 243 | +// MANIFEST |
| 244 | +Manifest-Version: 1.0 |
| 245 | +Bundle-ManifestVersion: 2 |
| 246 | +Bundle-Name: Contribution |
| 247 | +Bundle-SymbolicName: com.vogella.extensionpoint.contribution;singleton:=true |
| 248 | +Bundle-Version: 1.0.0.qualifier |
| 249 | +Require-Bundle: org.eclipse.core.runtime;bundle-version="3.32.0", |
| 250 | + com.vogella.extensionpoint.definition;bundle-version="1.0.0" |
| 251 | +Bundle-Vendor: VOGELLA |
| 252 | +Automatic-Module-Name: com.vogella.extensionpoint.contribution |
| 253 | +Bundle-RequiredExecutionEnvironment: JavaSE-21 |
| 254 | + |
| 255 | +``` |
| 256 | + |
| 257 | +```XML |
| 258 | +// plugin.xml |
| 259 | + |
| 260 | +``` |
| 261 | + |
| 262 | +```java |
| 263 | +// The client class that implemented attribute class |
| 264 | + |
| 265 | +package com.vogella.extensionpoint.contribution; |
| 266 | + |
| 267 | +import com.vogella.extensionpoint.definition.IGreeter; |
| 268 | + |
| 269 | +public class GreeterExensionContribution implements IGreeter { |
| 270 | + |
| 271 | + @Override |
| 272 | + public void greet() { |
| 273 | + System.err.println("This call from GreeterExensionContribution"); |
| 274 | + } |
| 275 | + |
| 276 | +} |
| 277 | +``` |
| 278 | + |
| 279 | +## 2.3. Accessing EXTENSIONS |
| 280 | +- The information about the available extensions point and the provided extensions are stored in a class of type `IExtensionRegistry` . |
| 281 | +- We can use the dependency injection mechanism to get the `IExtensionRegistry` class that injected. |
| 282 | +- `IExtensionRegistry` contains all extensions of all extensions point. |
| 283 | +```java |
| 284 | +// The following will read all existing extensions |
| 285 | +// for the defined ID of the extension point |
| 286 | +Platform.getExtensionRegistry(). |
| 287 | + getConfigurationElementsFor("yourextensionpointid"); |
| 288 | + |
| 289 | +``` |
| 290 | + |
| 291 | +```java |
| 292 | + IConfigurationElement[] elements = Platform.getExtensionRegistry() |
| 293 | + .getConfigurationElementsFor("com.renesas.cdt.devicesupport.api.builderDeviceSupport"); |
| 294 | + for (IConfigurationElement ele : elements) { |
| 295 | + |
| 296 | + } |
| 297 | + |
| 298 | +``` |
0 commit comments