commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
Subject svn commit: r991107 - in /commons/proper/digester/trunk/src/site: site.xml xdoc/plugins.xml
Date Tue, 31 Aug 2010 07:44:35 GMT
Author: simonetripodi
Date: Tue Aug 31 07:44:35 2010
New Revision: 991107

added the plugins page

    commons/proper/digester/trunk/src/site/xdoc/plugins.xml   (with props)

Modified: commons/proper/digester/trunk/src/site/site.xml
--- commons/proper/digester/trunk/src/site/site.xml (original)
+++ commons/proper/digester/trunk/src/site/site.xml Tue Aug 31 07:44:35 2010
@@ -34,6 +34,7 @@
     <menu name="Developers Guide">
       <item name="Core APIs"            href="/core.html"/>
+      <item name="Plugins"              href="/plugins.html"/>
       <item name="FAQ"                  href="/faq.html"/>

Added: commons/proper/digester/trunk/src/site/xdoc/plugins.xml
--- commons/proper/digester/trunk/src/site/xdoc/plugins.xml (added)
+++ commons/proper/digester/trunk/src/site/xdoc/plugins.xml Tue Aug 31 07:44:35 2010
@@ -0,0 +1,246 @@
+<?xml version="1.0" encoding="UTF-8"?>
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+See the License for the specific language governing permissions and
+limitations under the License.
+<document xmlns=""
+  xmlns:xsi=""
+  xsi:schemaLocation="">
+  <properties>
+    <title>Download Commons Digester</title>
+    <author email="">Commons Documentation Team</author>
+  </properties>
+  <body>
+    <section name="An overview of the Digester Plugins module.">
+      <p>Provides an easy mechanism whereby new digestion rules 
+can be added dynamically during a digestion.</p>
+      <subsection name="Introduction">
+        <p>Many applications have xml configuration files which are "extensible".
+Some examples of this are:</p>
+<li>Apache log4j allows user-provided "Appender" classes to be specified in 
+    its configuration file</li>
+<li>Apache Avalon allows "components" of a user-specified class</li>
+<li>Apache Ant allows custom tasks to be defined</li>
+<p>The Digester "plugins" module can be used to add this kind of functionality
+to your own applications.
+      </subsection>
+      <subsection name="An Example">
+        <p>Let's start off with an example.</p>
+Given the following digester rules in the main "parsing" application:</p>
+        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:
+    &lt;pipeline&gt;
+      &lt;source file="input.txt"/&gt;
+      &lt;transform plugin-class="SubstituteTransform"&gt;
+        &lt;from&gt;changeme&lt;/from&gt;
+        &lt;to&gt;changed&lt;/to&gt;
+      &lt;/transform&gt;
+      &lt;destination file="output.txt"/&gt;
+    &lt;/pipeline&gt;
+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.</p>
+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.</p>
+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.</p>
+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:</p>
+<li> declaring a method <code>public static void addRules(Digester d, String
+pattern)</code> on the class being "plugged in", or</li>
+<li> providing a separate "rule info" class, somewhat in the spirit of 
+"BeanInfo" classes for java beans, or</li>
+<li> providing an xmlrules file which defines the associated parsing rules.</li>
+<p>If a plugin class has a no-parameter constructor, does not expect any subtags, 
+and is satisfied with mapping any attributes on the parent xml tag to 
+bean-property-setter methods on itself, then no rules need to be defined at 
+all; the class can be used as a plugin without any coding.</p>
+In 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.</p>
+      </subsection>
+      <subsection name="Plugin Declarations">
+        <p>As well as the syntax shown above, where plugin classnames were defined
+as they were used, plugin classes can be pre-declared (provided the application
+associates a <code>PluginDeclarationRule</code> with a tag for that purpose).
+<p>The plugin class can be declared once:</p>
+  &lt;plugin id="widget" class="com.acme.Widget"/&gt;
+<p>and later referenced via the short "id" value:</p>
+  &lt;sometag plugin-id="widget" ... &gt;
+      </subsection>
+      <subsection name="Suggested Applications">
+        <p>Any application where user-specific operations may need to be performed
+that cannot be known in advance by the initial application developer may
+benefit from this module. Applications in the style of the Apache projects 
+listed at the top of this page (Log4j, Cocoon, Ant) are examples.</p>
+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.</p>
+      </subsection>
+      <subsection name="Terminology">
+        <p>The term "plugin declaration" refers to an xml element which matches a
+PluginDeclarationRule, where the user specifies an id-to-class mapping.</p>
+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).</p>
+      </subsection>
+      <subsection name="Limitations">
+        <p>The user cannot replace the <i>name</i> of the tag used as the
+<code>&lt;statement plugin-id="if"&gt;</code> cannot become &lt;if&gt;.</p>
+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.</p>
+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.
+      </subsection>
+      <subsection name="Performance">
+        <p>For patterns which do not involve "plugin points" there is minimal
+performance impact when adding rules to the Digester, and none when
+processing input data.</p>
+Processing elements which match patterns added dynamically by plugin classes 
+does have a performance impact, but not excessively so.</p>
+      </subsection>
+      <subsection name="Alternatives">
+        <p>The "xmlrules" digester module allows modification of parsing rules
+without code changes or recompilation. However this feature is aimed
+at the developer, not the end user of an application. The differences
+between xmlrules functionality and plugins functionality are:</p>
+With xmlrules, the full set of parsing rules for the whole configuration file
+is exposed. This is good for developers, but in most cases both too complex 
+and too dangerous to require end users to edit directly.
+Using xmlrules requires a fair level of knowledge of the Apache Digester.
+How an end user (not a plugin developer) can use plugins can be explained in 
+about 3 paragraphs. </li>
+      </subsection>
+      <subsection name="How to write plugin classes">
+        <p>In order to be useful, the problem domain needs to involve a base class
+interface which can have multiple implementations. This section assumes that
+this is the case, that you have already created a concrete implementation
+of that base class or interface, and are wondering what changes need to
+be made to that class to make it suitable for a "plugin".</p>
+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.</p>
+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.</p>
+Here is the addRules method on class SubstituteTransform, from the example:</p>
+    public static void addRules(Digester d, String pathPrefix) {
+        d.addCallMethod(pathPrefix+"/from", "setFrom", 0);
+        d.addCallMethod(pathPrefix+"/to", "setTo", 0);
+    }
+<p>A "rule info" class consists of nothing but a static method defined as above.</p>
+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.</p>
+Note that when adding any rules, the pattern passed to the digester
+<i>must</i> 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.</p>
+      </subsection>
+      <subsection name="Other features">
+        <p>Multiple plugin declarations are permitted; the latest simply overrides
+earlier ones.</p>
+In situations where a user <i>might</i> 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
+      </subsection>
+    </section>
+  </body>

Propchange: commons/proper/digester/trunk/src/site/xdoc/plugins.xml
    svn:eol-style = native

Propchange: commons/proper/digester/trunk/src/site/xdoc/plugins.xml
    svn:keywords = Date Revision Author HeadURL Id

Propchange: commons/proper/digester/trunk/src/site/xdoc/plugins.xml
    svn:mime-type = text/xml

View raw message