- 18.1. Nexus Plugins
-
- 18.1.1. Nexus Plugin API
- 18.1.2. Nexus Extension Points
- 18.1.3. Nexus Plugin Extension Points
-
- 18.1.3.1. Nexus Plugin Extension
- 18.1.3.2. Nexus Index HTML Customizer
- 18.1.3.3. Static Plugin Resources
- 18.1.3.4. Plugin Templates
- 18.1.3.5. Event Inspectors
- 18.1.3.6. Content Generators
- 18.1.3.7. Content Classes
- 18.1.3.8. Storage Implementations
- 18.1.3.9. Repository Customization
- 18.1.3.10. Item and File Inspectors
- 18.1.3.11. Nexus Feeds
- 18.1.3.12. Nexus Tasks and Task Configuration
- 18.1.3.13. Application Customization
- 18.1.3.14. Request Processing
- 18.2. Using the Nexus Plugin Archetype
- 18.3. Creating a Complex Plugin
- 18.4. Nexus Plugin Descriptor Maven Plugin
- 18.5. Defining Custom Repository Types
Among the many benefits of using an technology with an open source core is the ability to customize behavior and create extensions. To this end, Sonatype has spent a great deal of time designing an intuitive Plugin API that will allow you to take Nexus where you need it to go. This chapter summarizes some of these extension points and presents a walk through of how you would start to develop your own Nexus plugins.
Our community has already created a number of compelling and useful plugins, some of which have been integrated into the set of plugins that are distributed with both Nexus Open Source and Nexus Professional. Sonatype tried to make the Plugin API as lightweight and extensible as possible with the following goals in mind:
-
Providing a clear set of extension points for plugin developers
-
Providing isolated plugin classpaths to avoid compatibility issues between plugins and to prevent a plugin from disturbing another, unrelated part of Nexus.
-
Giving developers the ability to load and unload Nexus plugins at runtime
The Nexus API is contained in a module named nexus-api. If you are developing a Nexus plugin, you will need to familiarize yourself with the extension points that are defined in this project.
Nexus provides an extra module for plugin developers - the "nexus-plugin-api". This module provides some extra annotations for plugins developers, and it allows a plugin developer to implement a plugin without having to know anything about Plexus or Nexus internals.
The Plugin API uses the @Inject annotation, an emerging standard for dependency injection which allows Nexus plugins to be developed in a way that is container-neutral.
The Nexus Plugin API introduces some annotations to make things easier:
@Managed
When a @Managed annotation is present on an interface, it marks the interface as "component contract" (Plexus role). Any non-abstract classes implementing it will be made managed by current container.
@RepositoryType
Used on interfaces, to mark it as new repository type, and to be registered with other core repository types in Nexus Repository Type Registry. It holds the basic information about the new type (the path where to mount it).
@RestResource
Used on classes, to mark them as REST Resources.
The simplest Nexus plugin contain a single class, SampleEventInjector, which contributes an EventInspector to Nexus Application. This simple event inspector will do nothing more than print a message every time it accepts and inspects an event.
Example 18.1. A Simple Event Inspector
package org.sample.plugin;
import javax.inject.Inject;
import org.sonatype.nexus.proxy.events.EventInspector;
import org.sonatype.plexus.appevents.Event;
public class SampleEventInspector
implements EventInspector
{
public boolean accepts( Event<?> evt )
{
return true;
}
public void inspect( Event<?> evt )
{
System.out.println( "invoked with event: " +
evt.toString() + " with sender " +
evt.getEventSender().toString() );
}
}
During the build of this nexus plugin, this class is compiled and then scanned for concrete classes that implement extension point interfaces defined in the following section. The EventInspector interface in the nexus-api project has been marked with the @ExtensionPoint annotation. The plugin build takes the @ExtensionPoint, @Named, and @Inject annotations that may be present and generates a plugin descriptor which is packaged in the plugin's JAR.
When the plugin is present in Nexus during startup, the Nexus plugin manager reads the plugin metadata and instantiates the appropriate components. To implement a plugin, you simply implement some of these interfaces.
The following sections outline the available Nexus extension points.
-
Interface: org.sonatype.nexus.plugins.NexusPlugin
This extension component is meant to be used in Nexus plugins only. If it is found in a plugin, it will be invoked during install/uninstall/init phases of a plugin installation/uninstallation/initialization. Typical usage would be a need to perform some specific tasks on plugin install (ie. it uses native code to do some magic and those needs to be copied somewhere, register them with OS, etc).
-
Interface: org.sonatype.nexus.plugins.rest.NexusIndexHtmlCustomizer
This extension is able to customize the "index.html" returned by Nexus. Using this component, a plugin is able to add markup or Javascript to the pages generated by the Nexus web application. Every plugin that has a UI component uses this extension point to add Javascript customizations to the interface.
-
Interface: org.sonatype.nexus.plugins.rest.NexusResourceBundle
This extension gathers and publishes static resources over HTTP. These resources are usually JS files, CSS files, images, etc. Plugin developers do not need to use this extension directly since some of the features it exposes are automatic for all plugins. When the Nexus plugin manager discovers resources in plugin JAR under the path "/static", the Plugin Manager will create a special "plugin NexusResourceBundle" component on the fly.
If you do not want the plugin manager to automatically add a resource bundle you can define your own resource bundle implementation. The plugin manager will not add a resource bundle if:
-
no resources found on "/static" path within plugin classpath, or
-
a user created component of NexusResourceBundle exists within plugin
The "default plugin" resource bundle component uses MimeUtil from core to select MIME types of resources found within plugin, and will use same path to publish them (ie. in plugin JAR "/static/image.png" will be published on "http://nexushost/nexus/static/image.png").
-
Interface: org.sonatype.nexus.templates.TemplateProvider
Template provider is a component providing repository templates to Nexus. Every plugin which provides a "new" repository type should add a TemplateProvider as it is the only way to instantiate a repository instance. The core of Nexus provides a "default" template provider with templates for all core repository types, and all custom repository plugins (P2, OBR) provide template providers for their types.
-
Interface: org.sonatype.nexus.proxy.events.EventInspector
Event inspectors are used to inspect events in Nexus. One example of where this extension point is used is the index generation. To generate a Nexus index, there is an event inspector which listens for RepositoryItemEvent subclasses and updates the index in response to repository activity.
-
Interface: org.sonatype.nexus.proxy.item.ContentGenerator
A content generator is a component that is able to generate content dynamically, on the fly, instead of just serving a static resource. The content generator is registered to respond to a path that corresponds to a file. When the resource is retrieved, Nexus discards the file content and uses the registered content generator to generate content. The Nexus Archetype plugin uses a content generator to generate the archetype-catalog.xml. Every time a client requests the archetype-catalog.xml, the archetype catalog is generated using information from the index.
-
Interface: org.sonatype.nexus.proxy.registry.ContentClass
Content class controls the compatibility between repository types. It defines the type of content that can be stored in a repository, and it also affects how repositories can be grouped into repository groups. Every plugin contributing a new repository type should provide an instance of this extension point. Nexus has a ContentClass implementation for every core supported repository type, and the P2 and OBR plugins define custom ContentClass implementations.
-
Interface: org.sonatype.nexus.proxy.storage.local.LocalRepositoryStorage
-
Interface: org.sonatype.nexus.proxy.storage.remote.RemoteRepositoryStorage
A plugin developer can override the default file-based local repository storage and the default remote HTTP repository storage interface. If your plugin needs to stores repository artifacts and information in something other than a filesystem, or if your remote repository isn't accessible via HTTP, your plugin would provide an implementation of one of these interfaces. Nexus provides one of the each: a file-system LocalRepositoryStorage and CommonsHttpClient 3.x based RemoteRepositoryStorage.
-
Interface: org.sonatype.nexus.plugins.RepositoryCustomizer
This extension component will be invoked during configuration of every Repository instance, and may be used to add some "extra" configuration to repositories The procurement plugin uses this mechanism to "inject" RequestProcessor that will evaluate rules before allowing execution of request.
-
Interface: org.sonatype.nexus.proxy.attributes.StorageItemInspector
-
Interface: org.sonatype.nexus.proxy.attributes.StorageFileItemInspector
Attribute storage ItemInspectors are able to "decorate" items in repositories with custom attributes. Every file stored/cached/uploaded in Nexus will be sent to these components for inspection and potentially decoration. The StorageItemInspector will get all item types for inspection (file, collections, links), while StorageFileItemInspector will get only file items. Currently only one ItemInspector is used in Nexus: the checksumming inspector, that decorates all file items in Nexus with SHA1 checksum and stores it into item attributes.
-
Interface: org.sonatype.nexus.rest.feeds.sources.FeedSource
To add new RSS feeds, a plugin may provide implementation of this extension point. Nexus provides implementation for all the "core" RSS feeds.
-
Interface: org.sonatype.nexus.scheduling.NexusTask<T>
-
Interface: org.sonatype.nexus.tasks.descriptors.ScheduledTaskDescriptor
NexusTask is an extension point to implement new Nexus Scheduled Tasks.
If a contributed task needs UI, then the plugin which provides the NexusTask should provide a ScheduledTaskDescriptor which allows the UI customization for the task creation and management interface.
-
Interface: org.sonatype.nexus.rest.NexusApplicationCustomizer
This extension component is able to intercept URLs routed in the Nexus REST API layer.
