# 12. Plug-ins

Griffon provides a number of extension points that allow you to extend anything from the command line interface to the runtime configuration engine. The following sections detail how to go about it.

## 12.1 Creating and Installing Plug-ins

#### Creating Plug-ins

Creating a Griffon plugin is a simple matter of running the command:

    griffon create-plugin [PLUGIN NAME]

This will create a plugin project for the name you specify. Say for example you run `griffon create-plugin example`. This would create a new plugin project called `example`.

The structure of a Griffon plugin is exactly the same as a regular Griffon project's directory structure, except that in the root of the plugin directory you will find a plugin Groovy file called the "plugin descriptor".

The plugin descriptor itself ends with the convention `GriffonPlugin` and is found in the root of the plugin project. For example:

    class ExampleGriffonPlugin {
       def version = 0.1   …
    }

All plugins must have this class in the root of their directory structure to be valid. The plugin class defines the version of the plugin and optionally various hooks into plugin extension points (covered shortly).

You can also provide additional information about your plugin using several special properties:

- `title` - short one sentence description of your plugin
- `version` - the version of your plugin. Valid versions are for example "0.1", "0.2-SNAPSHOT", "0.1.4" etc.
- `griffonVersion` - The version of version range of Griffon that the plugin supports. eg. "1.1 > *"
- `license` - the plugin's license name in one sentence
- `pluginIncludes` - additional resources that should be included in the plugin zip
- `toolkits` - a list of supported toolkits [swing, javafx, swt, pivot, gtk]
- `platforms` - a list of supported platforms [linux, linux64, windows, windows64, macosx, macosx64, solaris, solaris64]
- `authosr` - a list of plugin author names/emails
- `description` - full multi-line description of plugin's features
- `documentation` - URL where plugin's documentation can be found
- `source` - URL where plugin's source can be found

Here is an example from Swing plugin :

    class SwingGriffonPlugin {
        String version = '0.9.5'
        String griffonVersion = '0.9.5 > *'
        Map dependsOn = [:]
        List pluginIncludes = []
        String license = 'Apache Software License 2.0'
        List toolkits = ['swing']
        List platforms = []
        String documentation = ''
        String source = 'https://github.com/griffon/griffon-swing-plugin'    List authors = [
            [
                name: 'Andres Almiray',
                email: 'aalmiray@yahoo.com'
            ]
        ]
        String title = 'Enables Swing support'
        String description = '''
    Enables the usage of Swing based components in Views.Usage
    ----
    This plugin enables the usage of the following nodes inside a View....Configuration
    -------------
    There's no special configuration for this plugin.[1]: http://groovy.codehaus.org/Swing+Builder
    '''
    }

#### Installing & Distributing Plugins

To distribute a plugin you need to navigate to its root directory in a terminal window and then type:

    griffon package-plugin

This will create a zip file of the plugin starting with `griffon-` then the plugin name and version. For example with the example plugin created earlier this would be `griffon-example-0.1.zip`. The `package-plugin` command will also generate `plugin.json` file which contains machine-readable information about plugin's name, version, author, and so on.

Once you have a plugin distribution file you can navigate to a Griffon project and type:

    griffon install-plugin /path/to/plugin/griffon-example-0.1.zip

If the plugin is hosted on a remote HTTP server you can also do:

    griffon install-plugin http://myserver.com/plugins/griffon-example-0.1.zip

#### Releasing Plugins into a Griffon Artifact Repository

To release a plugin call the `release-plugin` command while inside the plugin project. If no `repository` flag is specified then the default artifact repository (`griffon-central`) will be used. For quick testing purposes you can publish a release to `griffon-local` (which is always available) by issuing the following command

    griffon install-plugin --repository=griffon-local

The aforementioned steps can be applied to archetypes too, you just need to change the command names from `package-plugin` to `package-archetype`; from `install-plugin` to `install-archetype`; from `release-plugin` to `release-archetype`.

Should you decide to become a plugin/archetype author and wish to publish your artifacts to the Griffon Central repository then you must follow these steps:

- Create an account at http://artifacts.griffon-framework.org
- After confirming your email, log into your profile and click the button for membership request.
- Ping us at the developer mailing list or at @theaviary
- Once approved configure your credentials in `$USER_HOME/.griffon/settings.groovy` like this

    griffon.artifact.repositories = [
        'griffon-central': [
            username: 'yourUsername',
            password: 'yourPassword'
        ]
    ]

## 12.2 Artifact Repositories

There are 3 types of plugin repositories: `local`, `remote` and `legacy`. Artifact repositories can be either configured locally to a project (inside `griffon-app/conf/BuildConfig`) or globally to all projects (inside `$USER_HOME/.griffon/settings.groovy`),

#### Local Artifact Repositories

This type of repository is file based and can be hosted anywhere in the file system, even on shared folders over the network. Local repositories makes it easier to share snapshot releases among team mates as the network latency should be smaller. Their configuration requires but one parameter to be specified: the path where the artifacts will be placed. Here's a sample configuration for a local repository named '`my-local-repo`'.

    griffon.artifact.repositories = [
        'my-local-repo': [
            type: 'local',
            path: '/usr/local/share/griffon/repository'
        ]
    ]

There's a local repository available to you at all times. It's name is '`griffon-local`' and it's default path is `$USER_HOME/.griffon/repository`. This repository is the default place where downloaded plugins will be installed for speeding up retrievals at a later time.

#### Remote Artifact Repositories

This type of repository allows developers to publish releases via SCP or web. The repository is handled by a Grails application whose code is freely available at https://github.com/griffon/griffon-artifact-portal .

This code has been released under Apache Software License 2.0. Follow the instructions found in the README to run your own artifact portal. Configuring a remote repository requires a different set of properties than those exposed by local repositories. For example, if your organization is running a remote artifact repository located at `http://acme.com:8080/portal` then use the following configuration

    griffon.artifact.repositories = [
        'acme': [
            type: 'remote',
            url: 'http://acme.com:8080/portal'
        ]
    ]

You may specify additional properties such as

    griffon.artifact.repositories = [
        'acme': [
            type: 'remote',
            url: 'http://acme.com:8080/portal',
            username: 'wallace',
            password: 'gromit',
            port: 2345,
            timeout: 60
        ]
    ]

Where the following defaults apply

- port = 2222
- timeout = 30 (in seconds)

You may leave both `username` and `password` out however you will be asked for this credentials when publishing a release to this particular repository. Adding your credentials in the configuration avoids typing them when releasing artifacts.

#### Legacy Artifact Repository

This is a very special type of repository that exists only for backward compatibility during the migration of the old Griffon plugin repository to the new infrastructure in http://artifacts.griffon-framework.org .

There are no configuration options for this repository, neither you can publish a release to it; it's effectively read-only.

## 12.3 Understanding a Plugins Structure

As mentioned previously, a plugin is merely a project with an structure similar to a Griffon application with the addition of a contained plugin descriptor. However when installed, the structure of a plugin differs slightly. For example, take a look at this plugin directory structure:

    + griffon-app
         + controllers
         + models
         + views
         …
     + lib
     + src
         + main
         + cli
         + doc

Essentially when a plugin is installed into a project, the contents of the zip file will go into a directory such as `plugins/example-1.0/`. Plugin contents will not be copied into the main source tree. A plugin never interferes with a project's primary source tree.

## 12.4 Providing Basic Artefacts

#### Adding a new Script

A plugin can add a new script simply by providing the relevant Gant script within the scripts directory of the plugin:

    + MyPlugin.groovy
       + scripts     <-- additional scripts here
       + griffon-app
            + controllers
            + models
            + etc.
        + lib

#### Adding a new Controller, Model, View or Service

A plugin can add a new MVC Group, service or whatever by simply creating the relevant file within the `griffon-app` tree. However you'll need to create an Addon in order to package them properly.

    + ExamplePlugin.groovy
       + scripts
       + griffon-app
            + controllers  <-- additional controllers here
            + services <-- additional services here
            + etc.  <-- additional XXX here
        + lib

## 12.5 Hooking into Build Events

#### Post-Install Configuration and Participating in Upgrades

Griffon plugins can do post-install configuration and participate in application upgrade process (the upgrade command). This is achieved via two specially named scripts under `scripts` directory of the plugin - `_Install.groovy` and `_Upgrade.groovy`.

`_Install.groovy` is executed after the plugin has been installed and `_Upgrade.groovy` is executed each time the user upgrades his application with upgrade command.

These scripts are normal Gant scripts so you can use the full power of Gant. An addition to the standard Gant variables is the `pluginBasedir` variable which points at the plugin installation basedir.

As an example the below `_Install.groovy` script will create a new directory type under the `griffon-app` directory and install a configuration template:

    ant.mkdir(dir:"${basedir}/griffon-app/jobs")
    ant.copy(file:"${pluginBasedir}/src/samples/SamplePluginConfiguration.groovy",
             todir:"${basedir}/griffon-app/conf")// To access Griffon home you can use following code:
    // ant.property(environment:"env")
    // griffonHome = ant.antProject.properties."env.GRIFFON_HOME"

#### Scripting events

It is also possible to hook into command line scripting events through plugins. These are events triggered during execution of Griffon target and plugin scripts.

For example, you can hook into status update output (i.e. "Tests passed", "Server running") and the creation of files or artifacts.

A plugin merely has to provide an `_Events.groovy` script to listen to the required events. Refer the documentation on Hooking into Events for further information.

## 12.6 Addons

#### Understanding Addons

Addons are a plugin's best friend. While plugins can only contribute build-time artifacts (such as scripts) and participate on build events, addons may contribute runtime artifacts (such as MVC Groups or services) and participate on application events.

Often times whenever you'd like to package a reusable runtime artifact you'd have to create an Addon as well.

#### Addon responsibilities

Addons may contribute any of the following to your application: MVC Groups and application event handlers. They can also contribute the following to the CompositeBuilder: factories, methods, properties and FactoryBuilderSupport delegates (attribute, preInstantiate, postInstantiate, postNodeCompletion).

Addons are created using a template that suggests all of the properties and methods you can use configure. The complete list follows:

- `addonInit` - called right after the addon has been loaded but before contributions are taken into account
- `addonPostInit` - called after all contributions haven been made
- `addonBuilderInit` - called before contributions to the CompositeBuilder are taken into account
- `addonBuilderPostInit` - called after all CompositeBuilder contributions haven been made
- `events` - Map of additional application event handlers
- `factories` - Map of additional node factories, added to CompositeBuilder
- `methods` - Map of additional methods, added to CompositeBuilder
- `props` - Map of additional methods, added to CompositeBuilder
- `attributeDelegates` - List of attributeDelegates (as Closures), added to CompositeBuilder
- `preInstantiateDelegates` - List of preInstantiateDelegates (as Closures), added to CompositeBuilder
- `postInstantiateDelegates` - List of postInstantiateDelegates (as Closures), added to CompositeBuilder
- `postNodeCompletionDelegates` - List of postNodeCompletionDelegates (as Closures), added to CompositeBuilder

#### Configuring Addons

This task is done automatically for you when you package an addon inside a plugin. The plugin's `_Install` and `_Uninstall` scripts will make sure that `griffon-app/conf/Builder.groovy` stays up to date. When you install a plugin that contains an addon you'll notice that `Builder.groovy` may get updated with a line similar to the next one

    root.'CustomGriffonAddon'.addon=true

This means that all factories, methods and props defined on the Addon will be available to View scripts. However you need to explicitly specify which contributions should be made to other MVC members. You can list them one by one, or use a special group qualified by '*'. In recent releases of Griffon the default configuration is assumed meaning you won't see any changes in the `Builder.groovy` file. You can still apply modifications as explained below.

The following snippet shows how to configure an Addon to contribute all of its methods to Controllers, and all of its contributions to Models.

    root.'CustomGriffonAddon'.controller='*:methods'
    root.'CustomGriffonAddon'.model='*'

The special groups are: '*', '*:factories', '*:methods', '*:props'

Should you encounter a problem with duplicate node names you can change the default prefix (`root`) of the addon to something more suitable to your needs. All nodes contributed by the addon will now be accessible using that prefix. Here's an example

    nx.'CustomGriffonAddon'.addon=true

Assuming `CustomGriffonAddon` is defined as follows

    class CustomGriffonAddon {
        def factories = [
            button: com.acme.CustomButton
        ]
    }

Then instances of `CustomButtom` can be obtained by using `nxbutton`, whereas regular instances of `JButton` will be accessible with `button`.

## 12.7 Understanding Plugin Order

#### Controlling Plugin Dependencies

Plugins often depend on the presence of other plugins and can also adapt depending on the presence of others. To cover this, a plugin can define a `dependsOn` property. For example, take a look at this snippet from the Griffon Clojure plugin:

    class ClojureGriffonPlugin {
       def version = 0.3
       def dependsOn = ["lang-bridge": "0.2.1"]}

As the above example demonstrates the Clojure plugin is dependent on the presence of a single plugin: the `lang-bridge` plugin.

Essentially the dependencies will be loaded first and then the Clojure plugin. If all dependencies do not load, then the plugin will not load.

The `dependsOn` property also supports a mini expression language for specifying version ranges. A few examples of the syntax can be seen below:

    def dependsOn = [foo:"* > 1.0"]
    def dependsOn = [foo:"1.0 > 1.1"]
    def dependsOn = [foo:"1.0 > *"]

When the wildcard * character is used it denotes "any" version. The expression syntax also excludes any suffixes such as -BETA, -ALPHA etc. so for example the expression "1.0 > 1.1" would match any of the following versions:

- 1.1
- 1.0
- 1.0.1
- 1.0.3-SNAPSHOT
- 1.1-BETA2

#### Controlling Addon Load Order

Addons will be loaded in the order determined by the dependencies set forth in their containing plugins. Using `dependsOn` establishes a "hard" dependency. Any addons provided by the dependencies will be added first to the builder configuration file when installed.

## 12.8 CLI Dependencies

Plugins can provide compile time classes that should not be bundled with runtime classes (i.e, addon sources). Sources and resources placed under `$basedir/src/cli` will be automatically compiled and packaged into a jar whose name matches `griffon-${plugin.name}-${plugin.version}-compile.jar`. A typical use case for these type of classes is a custom AST transformation that should be run during compile time but not at runtime.