|
||||||||||
PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |
See:
Description
Interface Summary | |
---|---|
InitializableRule | Defines an interface that a Rule class can implement if it wishes to get an initialisation callback after the rule has been added to the set of Rules within a PluginRules instance. |
Class Summary | |
---|---|
Declaration | Represents a Class that can be instantiated by a PluginCreateRule, plus info on how to load custom digester rules for mapping xml into that plugged-in class. |
PluginContext | Provides data and services which should exist only once per digester. |
PluginCreateRule | Allows the original rules for parsing the configuration file to define points at which plugins are allowed, by configuring a PluginCreateRule with the appropriate pattern. |
PluginDeclarationRule | A Digester rule which allows the user to pre-declare a class which is to be referenced later at a plugin point by a PluginCreateRule. |
PluginManager | Coordinates between PluginDeclarationRule and PluginCreateRule objects, providing a place to share data between instances of these rules. |
PluginRules | A custom digester Rules manager which must be used as the Rules object when using the plugins module functionality. |
RuleFinder | Each concrete implementation of RuleFinder is an algorithm for locating a source of digester rules for a plugin. |
RuleLoader | Interface for classes which can dynamically load custom plugin rules associated with a user's plugin class. |
RulesFactory | Whenever the scope of a plugin tag is entered, the PluginRules class creates a new Rules instance and configures it with the appropriate parsing rules for the plugged-in class. |
Exception Summary | |
---|---|
PluginAssertionFailure | Thrown when a bug is detected in the plugins code. |
PluginConfigurationException | Thrown when an error occurs due to the way the calling application uses the plugins module. |
PluginException | Thrown when some plugin-related error has occurred, and none of the other exception types are appropriate. |
PluginInvalidInputException | Thrown when an error occurs due to bad data in the file being parsed. |
Provides an easy mechanism whereby new digestion rules can be added dynamically during a digestion.
Given the following digester rules in the main "parsing" application:
Digester digester = new Digester(); PluginRules rc = new PluginRules(); digester.setRules(rc); digester.addObjectCreate("pipeline", Pipeline.class); digester.addCallMethod("pipeline/source", "setSource", 1); digester.addCallParam("pipeline/source", 0, "file"); PluginCreateRule pcr = new PluginCreateRule(Transform.class); digester.addRule("pipeline/transform", pcr); digester.addSetNext("pipeline/transform", "setTransform"); digester.addCallMethod("pipeline/destination", "setDest", 1); digester.addCallParam("pipeline/destination", 0, "file"); digester.parse(filename);
the following input can be processed:
<pipeline> <source file="input.txt"/> <transform plugin-class="SubstituteTransform"> <from>changeme</from> <to>changed</to> </transform> <destination file="output.txt"/> </pipeline>
Note that the "SubstituteTransform" class is not hard-wired into the application, and also that this class is configuring itself from the same configuration file.
The user can specify any class they like here, and (provided that class follows the plugins conventions) it can use any Digester functionality to process the configuration data within the transform tag and its subtags.
The original application simply defined a "plugin point" of "pipeline/transform" at which user classes could be plugged in. However it did not specify what classes were permitted, other than that they must implement the Transform interface. It is the input file which has defined exactly which class should be instantiated when the transform element is encountered, and furthermore the "plugin" class itself has dynamically added rules for parsing elements nested within itself.
A class used as a plugin may dynamically add its own rules to the digester, in order to process its attributes and any subtags in any manner it wishes. This may be done by several mechanisms, including:
public static void addRules(Digester d, String
pattern)
on the class being "plugged in", orIn the example above, an end user may create their own classes which implement the required Transform interface, then cause these custom classes to be used instead of, or in addition to, classes distributed with the application.
PluginDeclarationRule
with a tag for that purpose). Example:
The plugin class can be declared once:
<plugin id="widget" class="com.acme.Widget"/>and later referenced via the short "id" value:
<sometag plugin-id="widget" ... >
Note also that plugged-in classes can themselves allow user-defined classes to be plugged in within their configuration. This allows a very simple framework to be extended almost without limit by the end user.
The term "plugin point" refers to a pattern associated with a PluginCreateRule. An xml element matching that pattern is expected to have a plugin-id attribute (but see note on "default plugins" elsewhere in this document).
<statement plugin-id="if">
cannot become <if>.
An instance of "PluginRules" must be used as the Rules implementation for the Digester (see example). However a PluginRules can use any other Rules implementation as its rule-matching engine, so this is not a significant issue. Plugged-in classes may only use the default RulesBase matching for the rules they add dynamically.
For technical reasons, a single instance of PluginCreateRule cannot currently be associated with multiple patterns; multiple instances are required. This is not expected to be a problem.
Processing elements which match patterns added dynamically by plugin classes does have a performance impact, but not excessively so.
Well, if the class has a no-argument constuctor, and only simple configuration needs that can be met by a SetPropertiesRule, then no changes need to be made at all.
In other circumstances, you may either define an "addRules" method on the class which adds any necessary rules to the digester, a separate class containing that information, or write an xmlrules-format file defining the necessary rules. In the "separate rule info class" approach, the class containing the rule info may have any name of your choice, but the original class + "RuleInfo" is recommended.
Here is the addRules method on class SubstituteTransform, from the example:
public static void addRules(Digester d, String pathPrefix) { d.addCallMethod(pathPrefix+"/from", "setFrom", 0); d.addCallMethod(pathPrefix+"/to", "setTo", 0); }A "rule info" class consists of nothing but a static method defined as above.
If a plugin class does not define an "addRules" method, and the plugin declaration does not associate a rule info class with it, then the plugins module will define a "SetPropertiesRule" by default. However if any custom rules are defined for the plugin class, then that implementation is required to define a SetPropertiesRule for itself if it desires one.
Note that when adding any rules, the pattern passed to the digester must start with the pathPrefix provided. A plugin cannot define rules with absolute paths. And as defined in the limitations, the pattern should not include any wildcard characters.
In situations where a user might want to specify a custom class, but will often want "default" behaviour, a PluginCreateRule can specify a default class. If the user then omits the "plugin-id" attribute on the matching xml element, an instance of the default class will be created.
|
||||||||||
PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |