Context Docs: Plugins
The primary method whereby any Context assumes its behavior, be it a PluggableContext or an HTTPContext, is through one or more registered Plugins.
We won't be talking about how to create a custom plugin in this section, that's a more involved topic for later on. For now we will be focusing on the anatomy of a plugin and how exactly the two different types interact with a Context instance.
To start, the Context interface provides a few helpful methods as a part of it's API that are plugin-centric;
These methods allow you to register a plugin with the context, ask the context if it has a specific plugin and ask the context to return a managed instance of a registered plugin.
Before we get any further, it's important that we dive into the Plugin interface API. This interface, in concert with the Context plugin methods detailed above combine to produce almost the entirety of the Context dynamic behaviors. Below is the Plugin interface API;
It's important to note that although the type of the "class" argument within the read() method is specified as "any", you can guarantee that the argument type is actually an instance of org.cfcommons.reflection.Class. "Any" is specified because of a bug in interface typing on the part of CF.
The Plugin interfaces very closely related subtype is HTTPPlugin, which looks like this;
Any component that you create that implements the above Plugin OR HTTPPlugin interface can be easily registered with a parent context via the Context addPlugin() method.
Plugin Initialization
A very important process is fired whenever you register a Plugin instance with a Context. The Context will iterate through each managed Class instance and pass a reference into the read() method of the plugin. This happens the moment addPlugin() is invoked on the Context. This ensures that your plugin can initialize itself with any information it may require from the contents of the Context. For instance, many of the standard plugins that are provided with the context distribution rely on class and method level annotations in some form or another, is it through the above initialization process that those plugins extrapolate annotation information provided very easily by the reflective Class API. Because the Context manages a registry of root Class instances (determine by it's root value), a reflective Class is not recreated for each plugin, it simply provides the reference from it's internal cache - so the process in and of itself is not very expensive or resource intensive. Of course, that also depends upon how the plugin itself was coded.
Decorating Context Behavior
The purpose of a Plugin is to change or otherwise enhance the behavior of it's parent Context. This allows any context consumer to utilize it in a manner prescribed by it's registered plugins. The first method is by dynamically altering the Context API. An instance of a Plugin of course can have as many methods declared on it as needed - just as long as it meets the contract of either the Plugin or HTTPPlugin interfaces. Any public methods declared on a plugin that are not members of either contract, will be available on the parent Context as soon as the context is constructed. For instance, if a plugin has a public method named doSomething() declared on it, after it's parent context has been initialized, you can invoke the doSomething() method on the Context itself and expect the behavior declared within it's containing plugin. The Context acts as a facade to the plugin behavior.
Participating in Context Class Instantiation
The second method that a Plugin can leverage to alter context behavior is participating in the instantiation and initialization of context Class instances. The Context interface exposes a public method named getObjectInstance(). The argument that this method requires is a string representing the dot-notation fullname of a Class that the context maintains (again, determined by it's root). You can ask the Context to create an object instance for you by invoking this method. Under the covers the Context employs an object factory of type MutableObjectFactory that collaborates with ObjectDecorator instances to produce a final object instance. This approach to object instantiation coincides with the collaborative plugin architecture of the context - meaning any plugin now can register one or more instances of ObjectDecorator with the MutableObjectFactory and "participate" in how object instances are created. For instance, the SimpleSecurityPlugin provides a comprehensive class-based security framework that allows you to annotate security algorithms for class methods. That plugin utilizes the cfcommons Aspect Oriented Programming library AND the MutableObjectFactory API to register a specific instance of ObjectDecorator. So when any instance of a class is requested from the context while the security plugin exists, and that objects class has been annotated correctly, the instance returned will be correctly initialized with all of the proper security cross-cutting concerns.
Collaborative Plugin architecture
Plugin instances maintain a reference to their parent Context, and as such can easily collaborate with other registered plugins if necessary through the plugin-centric methods of the Context. This is all a part of the collaborate plugin archiecture which is intended to allow any custom plugins to communicate with any other registered plugins if necessary.
Standard Plugins
The Context module distribution comes with a handful "standard" plugins. Each is meant provide common and useful functionality to any context that employs them, you can check them out under the "standard plugins" section of the context home page located here .
Pre-packaged Plugin Stacks
While generally speaking the responsibility of configuring a plugin to work with your context is your responsibility, we've gone ahead and "packaged" different variations of the standard plugins into pre-configured plugin stacks. These stacks allow you to get up and running with a context quickly and easily. You can find the pre-packaged plugin stacks under the same link on the context main page located here .