From 29ca9f74df42f9bf0a7c2395b2c61789445b5fe6 Mon Sep 17 00:00:00 2001 From: Mykola Morhun Date: Fri, 30 Aug 2019 11:55:56 +0000 Subject: [PATCH] Add plugins resources provider contribution point Signed-off-by: Mykola Morhun --- .../plugin-ext/src/common/plugin-protocol.ts | 19 +++++++++++++++ .../src/hosted/node/plugin-reader.ts | 23 ++++++++++++++++--- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/packages/plugin-ext/src/common/plugin-protocol.ts b/packages/plugin-ext/src/common/plugin-protocol.ts index bd515f9a112c3..c07647441c7c0 100644 --- a/packages/plugin-ext/src/common/plugin-protocol.ts +++ b/packages/plugin-ext/src/common/plugin-protocol.ts @@ -585,6 +585,25 @@ export interface MetadataProcessor { process(pluginMetadata: PluginMetadata): void; } +/** + * Designed to retreive plugins resources from non default or remote location. + */ +export const PluginResourcesProvider = Symbol.for('ResourcesProvider'); +export interface PluginResourcesProvider { + /** + * Checks if this provider has resources for the given plugin. + * @param pluginId id of plugin to check presence of resources for + */ + hasResources(pluginId: string): boolean; + + /** + * Returns resource by given path or undefined if no resource exists. + * @param pluginId id of plugin that requests resource is for. + * @param resourcePath path to requested resource. Might be relative to plugin location + */ + getResource(pluginId: string, resourcePath: string): Promise; +} + export function getPluginId(plugin: PluginPackage | PluginModel): string { return `${plugin.publisher}_${plugin.name}`.replace(/\W/g, '_'); } diff --git a/packages/plugin-ext/src/hosted/node/plugin-reader.ts b/packages/plugin-ext/src/hosted/node/plugin-reader.ts index 8f80c724a6d88..9b979e7d2fbb4 100644 --- a/packages/plugin-ext/src/hosted/node/plugin-reader.ts +++ b/packages/plugin-ext/src/hosted/node/plugin-reader.ts @@ -23,7 +23,7 @@ import * as escape_html from 'escape-html'; import { ILogger } from '@theia/core'; import { inject, injectable, optional, multiInject } from 'inversify'; import { BackendApplicationContribution } from '@theia/core/lib/node/backend-application'; -import { PluginMetadata, getPluginId, MetadataProcessor } from '../../common/plugin-protocol'; +import { PluginMetadata, getPluginId, MetadataProcessor, PluginResourcesProvider } from '../../common/plugin-protocol'; import { MetadataScanner } from './metadata-scanner'; @injectable() @@ -36,7 +36,12 @@ export class HostedPluginReader implements BackendApplicationContribution { private readonly scanner: MetadataScanner; @optional() - @multiInject(MetadataProcessor) private readonly metadataProcessors: MetadataProcessor[]; + @multiInject(MetadataProcessor) + private readonly metadataProcessors: MetadataProcessor[]; + + @optional() + @multiInject(PluginResourcesProvider) + private readonly resourcesProvider: PluginResourcesProvider[]; /** * Map between a plugin's id and the local storage @@ -44,7 +49,7 @@ export class HostedPluginReader implements BackendApplicationContribution { private pluginsIdsFiles: Map = new Map(); configure(app: express.Application): void { - app.get('/hostedPlugin/:pluginId/:path(*)', (req, res) => { + app.get('/hostedPlugin/:pluginId/:path(*)', async (req, res) => { const pluginId = req.params.pluginId; const filePath = req.params.path; @@ -54,6 +59,18 @@ export class HostedPluginReader implements BackendApplicationContribution { res.status(404).send(`No such file for plugin with id '${escape_html(pluginId)}'.`); }); } else { + // Requested resource is not local. Check providers if any. + for (const provider of this.resourcesProvider) { + if (provider.hasResources(pluginId)) { + const resource = await provider.getResource(pluginId, filePath); + if (resource) { + res.type(path.extname(filePath)); + res.send(resource); + return; + } + } + } + res.status(404).send(`The plugin with id '${escape_html(pluginId)}' does not exist.`); } });