Resource API

Last modified by Admin on 2024/10/28 19:04

cogAn abstraction of a XWiki URI (Entity, Template, Skin, etc)
TypeJAR
Category
Developed by

XWiki Development Team

Rating
0 Votes
LicenseGNU Lesser General Public License 2.1
Bundled With

XWiki Standard

Installable with the Extension Manager

Description

A resource in XWiki represents something that can be accessed. For example Entities, Templates, Skin files, Files on the filesystem, Temporary files generated by Macros, etc.

It can be viewed as a URI or as an abstraction of an XWiki URL.

API Tour

The following classes/interfaces are available:

  • ResourceType: Represents a type of Resource (eg Entities, Templates, Skin files, Files on the filesystem, Temporary files generated by Macros, etc).
  • ResourceReference: represents a reference to a Resource. EntityResourceReference represent a reference to an Entity resource (document, space, page, wiki, etc).
  • ResourceTypeResolver: Extract the ResourceType from a representation (text, URL, etc). 7.1M1
  • ResourceReferenceResolver: Create a ResourceReference object from a representation (text, URL, etc). For example the StandardURLResourceReferenceResolver is used to create a ResourceReference out of an URL written using the "standard" format.
  • ResourceReferenceSerializer: A component role type to convert a Resource reference into something else. For example, the URL module provides a StandardExtendedURLResourceReferenceSerializer to generate a URL out of Resource reference (note that the implementation is not complete as of now and shouldn't be used for the moment).
  • ResourceReferenceManager: Provides a getResource() method to access the current resource being processed (located in the Execution Context).
  • ResourceLoader: Load Resources pointed to by Resource Reference as an Input Stream (not used yet)
  • EntityResourceAction: Represents the action to be executed on an Entity Resource (eg view, delete, get, etc).
  • ResourceReferenceHandler: Handles a ResourceReference by executing some actions. For example, for the bin Resource type (which is an Entity Resource Type) this means executing various actions (view, edit, download, etc) for that Entity.
  • ResourceReferenceHandlerManager: Entry point for handling Resource References. Will find the proper ResourceReferenceHandler to know how to handle that Resource type and put them in the right priority order.

Resource Reference Handling

This part of the Resource module is in charge of calling the correct backend code to display what the user has asked for (it's the Controller in MVC terminology).

Right now most Actions are still implemented the old way in the oldcore module without Components and using Struts. The goal is to progressively rewrite them using this new Resource Reference Handler API. Check the WebJars Module For an example of registering a new ResourceType and ResourceReferenceHandler.

This API supports the following use cases:

  • UC1: Handlers should be able to be added without touching at the existing platform code (i.e. someone could write a new Handler in java and plug it in)
  • UC2: It should be possible to execute something before or after a Handler's execution.
  • UC3: It should be possible to completely replace a Handler with another implementation.
  • UC4: It should be possible to add Handlers without stopping the running XWiki instance.
  • UC5: Handlers should not know about each other.
  • UC6: Handlers should be independent of the URL formats used.
  • UC7: Handlers should work for any type of Resource (Entity Resources, Temporary Resources, Skin Resources, etc).
  • UC8: It should be possible for a Handler to be registered for one Resource type, a list of Resource types, or all types.

Adding a new Resource Type Handler

Extensions can register a new URL Resource Type. 

When contributing an extension adding a new ResourceReferenceHandler component implementation, make sure to indicate in the pom that the extension is installed in the root namespace. The reason is that the new URL format is parsed as one of the first thing in XWiki (precisely in RoutingFilter) and the component manager used to locate your ResourceReferenceHandler is the root Component Manager.

Specifically, add the following property to your Maven module's pom.xml:

<xwiki.extension.namespaces>{root}</xwiki.extension.namespaces>

Here's an example of a webjars Resource Type that would be called for the following types of URLs: http://<server>/<context path>/webjars/<path/to/resource/>.

@Component
@Named("webjars")
@Singleton
public class WebJarsResourceReferenceHandler extends AbstractResourceReferenceHandler<ResourceType>
{
   /**
     * The WebJars Type.
     */

   public static final ResourceType TYPE = new ResourceType("webjars");

   @Override
   public List<ResourceType> getSupportedResourceReferences()
   {
       return Arrays.asList(TYPE);
   }

   @Override
   public void handle(ResourceReference resourceReference, ResourceReferenceHandlerChain chain)
       throws ResourceReferenceHandlerException
   {
       [...]
   }
}

Adding a new Entity Resource Type Handler

Entity Resource References are handled by a ResourceReferenceHandler component with hint bin (that name corresponds to the part of the URL showing that it's a URL about an Entity). That ResourceReferenceHandler, in turn, looks for ResourceReferenceHandler components that are registered for the EntityResourceAction to execute (view, edit, download, etc) and calls them in the right priority order.

Here's an example of a webjars Entity Resource Action that would be called for the following types of URLs: http://<server>/<context path>/bin/webjars/resource/path?value=<resource name>.

@Component
@Named("webjars")
@Singleton
public class WebJarsResourceReferenceHandler extends AbstractResourceReferenceHandler<EntityResourceAction>
{
   /**
     * The WebJars Action.
     */

   public static final EntityResourceAction ACTION = new EntityResourceAction("webjars");

   /**
     * Prefix for locating JS resources in the classloader.
     */

   private static final String WEBJARS_RESOURCE_PREFIX = "META-INF/resources/webjars/";

   @Inject
   private Container container;

   @Override
   public List<EntityResourceAction> getSupportedResourceReferences()
   {
       return Arrays.asList(ACTION);
   }

   @Override
   public void handle(ResourceReference reference, ResourceReferenceHandlerChain chain)
       throws ResourceReferenceHandlerException
   {
        String resourceName = reference.getParameterValue("value");
        String resourcePath = String.format("%s%s", WEBJARS_RESOURCE_PREFIX, resourceName);

        InputStream resourceStream = getClassLoader().getResourceAsStream(resourcePath);

       if (resourceStream != null) {
           try {
                IOUtils.copy(resourceStream, this.container.getResponse().getOutputStream());
           } catch (IOException e) {
               throw new ResourceReferenceHandlerException(
                    String.format("Failed to read resource [%s]", resourceName), e);
           } finally {
                IOUtils.closeQuietly(resourceStream);
           }
       }

       // Be a good citizen, continue the chain, in case some lower-priority Handler has something to do for this
       // Resource Reference.
       chain.handleNext(reference);
   }

   /**
     * @return the Class Loader from which to look for WebJars resources
     */

   protected ClassLoader getClassLoader()
   {
       // Load the resource from the context class loader in order to support webjars located in XWiki Extensions
       // loaded by the Extension Manager.
       return Thread.currentThread().getContextClassLoader();
   }
}

The context

By default, a ResourceReferenceHandler is called without any initialized XWikiContext.

If you need one with the current user automatically authenticated (to check if the user is allowed to access this resource, for example), you can annotate the handler with @org.xwiki.resource.annotations.Authenticated. It will also trigger the initialization of XWiki (and wait for it to finish) when it's not already the case.

Known Resource Types

Prerequisites & Installation Instructions

We recommend using the Extension Manager to install this extension (Make sure that the text "Installable with the Extension Manager" is displayed at the top right location on this page to know if this extension can be installed with the Extension Manager).

You can also use the manual method which involves dropping the JAR file and all its dependencies into the WEB-INF/lib folder and restarting XWiki.

Dependencies

Dependencies for this extension (org.xwiki.platform:xwiki-platform-resource-api 16.9.0):

Get Connected