From fec80129c96cff953d9d215f1332d9188bd7de32 Mon Sep 17 00:00:00 2001 From: Claude Brisson Date: Sun, 10 Mar 2019 22:22:32 +0000 Subject: [engine][VELOCITY-909] Propagate propnames changes thorough javadoc; some more related code fixes git-svn-id: https://svn.apache.org/repos/asf/velocity/engine/branches/VELOCITY-909@1855176 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/velocity/context/AbstractContext.java | 2 +- .../runtime/DeprecatedRuntimeConstants.java | 29 +++- .../apache/velocity/runtime/RuntimeConstants.java | 35 ++++- .../apache/velocity/runtime/RuntimeInstance.java | 2 +- .../apache/velocity/runtime/RuntimeSingleton.java | 2 +- .../apache/velocity/runtime/directive/Parse.java | 2 +- .../runtime/resource/ResourceManagerImpl.java | 8 +- .../resource/loader/ClasspathResourceLoader.java | 8 +- .../resource/loader/DataSourceResourceLoader.java | 147 +++++++++++---------- .../runtime/resource/loader/JarResourceLoader.java | 8 +- .../resource/loader/StringResourceLoader.java | 15 ++- .../org/apache/velocity/util/ExtProperties.java | 4 +- .../util/introspection/LinkingUberspector.java | 2 +- 13 files changed, 160 insertions(+), 104 deletions(-) (limited to 'velocity-engine-core/src/main/java/org') diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/context/AbstractContext.java b/velocity-engine-core/src/main/java/org/apache/velocity/context/AbstractContext.java index 4e62c4e3..eae05477 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/context/AbstractContext.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/context/AbstractContext.java @@ -164,7 +164,7 @@ public abstract class AbstractContext extends InternalContextBase /* * We always use string interning here: * 1) speed is generally less critical when populating the context than during parsing or rendering - * 2) a context key is very likely to be used several times, or even a lot of times, in the template (but does it save memory if runtime.string.interning is false?) + * 2) a context key is very likely to be used several times, or even a lot of times, in the template (but does it save memory if runtime.string_interning is false?) * 3) last but not least: we don't have access to RuntimeServices from here, the reengineering would be painful... */ return internalPut(key.intern(), value); diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/DeprecatedRuntimeConstants.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/DeprecatedRuntimeConstants.java index 09d0b9ca..2d876919 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/DeprecatedRuntimeConstants.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/DeprecatedRuntimeConstants.java @@ -123,7 +123,34 @@ public interface DeprecatedRuntimeConstants */ String OLD_RESOURCE_LOADER_CHECK_INTERVAL = "modificationCheckInterval"; - /** The default character encoding for the templates. Used by the parser in processing the input streams. */ + /** + * Datasource loader datasource url + * @deprecated see {@link RuntimeConstants#DS_RESOURCE_LOADER_DATASOURCE} + */ + String OLD_DS_RESOURCE_LOADER_DATASOURCE = "ds.resource.loader.resource.datasource"; + + /** + * Datasource loader template key column + * @deprecated see {@link RuntimeConstants#DS_RESOURCE_LOADER_KEY_COLUMN} + */ + String OLD_DS_RESOURCE_LOADER_KEY_COLUMN = "ds.resource.loader.resource.keycolumn"; + + /** + * Datasource loader template content column + * @deprecated see {@link RuntimeConstants#DS_RESOURCE_LOADER_TEMPLATE_COLUMN} + */ + String OLD_DS_RESOURCE_LOADER_TEMPLATE_COLUMN = "ds.resource.loader.resource.templatecolumn"; + + /** + * Datasource loader template timestamp column + * @deprecated see {@link RuntimeConstants#DS_RESOURCE_LOADER_TIMESTAMP_COLUMN} + */ + String OLD_DS_RESOURCE_LOADER_TIMESTAMP_COLUMN = "ds.resource.loader.resource.timestampcolumn"; + + /** + * The default character encoding for the templates. Used by the parser in processing the input streams. + * @deprecated see {@link RuntimeConstants#INPUT_ENCODING} + */ String OLD_INPUT_ENCODING = "input.encoding"; /** diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeConstants.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeConstants.java index 830f5f80..ffc09c03 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeConstants.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeConstants.java @@ -167,7 +167,7 @@ public interface RuntimeConstants extends DeprecatedRuntimeConstants /** * Key used to retrieve the names of the resource loaders to be used. In a properties file they may appear as the following: * - *

resource.loader = file,classpath

+ *

resource.loaders = file,classpath

*/ String RESOURCE_LOADERS = "resource.loaders"; @@ -211,6 +211,31 @@ public interface RuntimeConstants extends DeprecatedRuntimeConstants */ String RESOURCE_LOADER_CHECK_INTERVAL = "modification_check_interval"; + /** + * Datasource loader datasource url + */ + String DS_RESOURCE_LOADER_DATASOURCE = "resource.loader.ds.resource.datasource_url"; + + /** + * Datasource loader templates table + */ + String DS_RESOURCE_LOADER_TABLE = "resource.loader.ds.resource.table"; + + /** + * Datasource loader template key column + */ + String DS_RESOURCE_LOADER_KEY_COLUMN = "resource.loader.ds.resource.key_column"; + + /** + * Datasource loader template content column + */ + String DS_RESOURCE_LOADER_TEMPLATE_COLUMN = "resource.loader.ds.resource.template_column"; + + /** + * Datasource loader template timestamp column + */ + String DS_RESOURCE_LOADER_TIMESTAMP_COLUMN = "resource.loader.ds.resource.timestamp_column"; + /** The default character encoding for the templates. Used by the parser in processing the input streams. */ String INPUT_ENCODING = "resource.default_encoding"; @@ -224,25 +249,25 @@ public interface RuntimeConstants extends DeprecatedRuntimeConstants */ /** - * The eventhandler.referenceinsertion.class property specifies a list of the + * The event_handler.reference_insertion.class property specifies a list of the * {@link org.apache.velocity.app.event.ReferenceInsertionEventHandler} implementations to use. */ String EVENTHANDLER_REFERENCEINSERTION = "event_handler.reference_insertion.class"; /** - * The eventhandler.methodexception.class property specifies a list of the + * The event_handler.method_exception.class property specifies a list of the * {@link org.apache.velocity.app.event.MethodExceptionEventHandler} implementations to use. */ String EVENTHANDLER_METHODEXCEPTION = "event_handler.method_exception.class"; /** - * The eventhandler.include.class property specifies a list of the + * The event_handler.include.class property specifies a list of the * {@link org.apache.velocity.app.event.IncludeEventHandler} implementations to use. */ String EVENTHANDLER_INCLUDE = "event_handler.include.class"; /** - * The eventhandler.invalidreferences.class property specifies a list of the + * The event_handler.invalid_references.class property specifies a list of the * {@link org.apache.velocity.app.event.InvalidReferenceEventHandler} implementations to use. */ String EVENTHANDLER_INVALIDREFERENCES = "event_handler.invalid_references.class"; diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeInstance.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeInstance.java index 318bb0a2..8350299c 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeInstance.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeInstance.java @@ -1543,7 +1543,7 @@ public class RuntimeInstance implements RuntimeConstants, RuntimeServices /** * Returns a Template from the resource manager. * This method assumes that the character encoding of the - * template is set by the input.encoding + * template is set by the resource.default_encoding * property. The default is UTF-8. * * @param name The file name of the desired template. diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeSingleton.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeSingleton.java index 78f31e9f..29164f81 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeSingleton.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeSingleton.java @@ -269,7 +269,7 @@ public class RuntimeSingleton implements RuntimeConstants /** * Returns a Template from the resource manager. * This method assumes that the character encoding of the - * template is set by the input.encoding + * template is set by the resource.default_encoding * property. The default is UTF-8. * * @param name The file name of the desired template. diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Parse.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Parse.java index d52da38e..0a472273 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Parse.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Parse.java @@ -55,7 +55,7 @@ import java.util.List; * content. * * 2) There is a limited parse depth. It is set as a property - * "directive.parse.max.depth = 10" by default. This 10 deep + * "directive.parse.max_depth = 10" by default. This 10 deep * limit is a safety feature to prevent infinite loops. * * diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/ResourceManagerImpl.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/ResourceManagerImpl.java index 91058d68..68644561 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/ResourceManagerImpl.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/ResourceManagerImpl.java @@ -69,7 +69,7 @@ public class ResourceManagerImpl * This is a list of the template input stream source initializers, basically properties for a particular template stream * source. The order in this list reflects numbering of the properties i.e. * - *

<loader-id>.resource.loader.<property> = <value>

+ *

resource.loader.<loader-id>.<property> = <value>

*/ private final List sourceInitializerList = new ArrayList<>(); @@ -127,9 +127,9 @@ public class ResourceManagerImpl resourceLoader = ResourceLoaderFactory.getLoader(rsvc, loaderClass); } else { - String msg = "Unable to find '" + + String msg = "Unable to find 'resource.loader." + configuration.getString(RuntimeConstants.RESOURCE_LOADER_IDENTIFIER) + - ".resource.loader.class' specification in configuration." + + ".class' specification in configuration." + " This is a critical value. Please adjust configuration."; log.error(msg); throw new VelocityException(msg); @@ -215,7 +215,7 @@ public class ResourceManagerImpl /* * The loader id might look something like the following: * - * file.resource.loader + * resource.loader.file * * The loader id is the prefix used for all properties * pertaining to a particular loader. diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/ClasspathResourceLoader.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/ClasspathResourceLoader.java index ea579cd0..50443df8 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/ClasspathResourceLoader.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/ClasspathResourceLoader.java @@ -46,10 +46,10 @@ import java.io.Reader; * other than specifying this as the loader to use. For example * the following is all that the loader needs to be functional: *
- *
- * resource.loader = class - * class.resource.loader.class = - * org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader + *

+ *  resource.loaders = class
+ *  resource.loader.class.class =org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
+  * 
*
*
* To use, put your template directories, jars diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/DataSourceResourceLoader.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/DataSourceResourceLoader.java index c919bc07..853b93e8 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/DataSourceResourceLoader.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/DataSourceResourceLoader.java @@ -21,6 +21,7 @@ package org.apache.velocity.runtime.resource.loader; import org.apache.velocity.exception.ResourceNotFoundException; import org.apache.velocity.exception.VelocityException; +import org.apache.velocity.runtime.RuntimeConstants; import org.apache.velocity.runtime.resource.Resource; import org.apache.velocity.util.ExtProperties; @@ -40,84 +41,86 @@ import java.sql.SQLException; import java.sql.Timestamp; /** - *

This is a simple template file loader that loads templates - * from a DataSource instead of plain files. + *

This is a simple template file loader that loads templates + * from a DataSource instead of plain files.

* - *

It can be configured with a datasource name, a table name, + *

It can be configured with a datasource name, a table name, * id column (name), content column (the template body) and a - * datetime column (for last modification info). + * datetime column (for last modification info).

*
+ *

Example configuration snippet for velocity.properties:

*
- * Example configuration snippet for velocity.properties: - *
- *
- * resource.loader = file, ds
- *
- * ds.resource.loader.public.name = DataSource
- * ds.resource.loader.description = Velocity DataSource Resource Loader
- * ds.resource.loader.class = org.apache.velocity.runtime.resource.loader.DataSourceResourceLoader
- * ds.resource.loader.resource.datasource = java:comp/env/jdbc/Velocity
- * ds.resource.loader.resource.table = tb_velocity_template
- * ds.resource.loader.resource.keycolumn = id_template
- * ds.resource.loader.resource.templatecolumn = template_definition
- * ds.resource.loader.resource.timestampcolumn = template_timestamp
- * ds.resource.loader.cache = false
- * ds.resource.loader.modificationCheckInterval = 60
- *
- *

Optionally, the developer can instantiate the DataSourceResourceLoader and set the DataSource via code in - * a manner similar to the following: - *
- *
- * DataSourceResourceLoader ds = new DataSourceResourceLoader();
- * ds.setDataSource(DATASOURCE);
- * Velocity.setProperty("ds.resource.loader.instance",ds);
- *

The property ds.resource.loader.class should be left out, otherwise all the other - * properties in velocity.properties would remain the same. - *
- *
+ *


+ * resource.loaders = file, ds
  *
- * Example WEB-INF/web.xml: 
+ * resource.loader.ds.description = Velocity DataSource Resource Loader
+ * resource.loader.ds.class = org.apache.velocity.runtime.resource.loader.DataSourceResourceLoader
+ * resource.loader.ds.resource.datasource_url = java:comp/env/jdbc/Velocity
+ * resource.loader.ds.resource.table = tb_velocity_template
+ * resource.loader.ds.resource.key_column = id_template
+ * resource.loader.ds.resource.template_column = template_definition
+ * resource.loader.ds.resource.timestamp_column = template_timestamp
+ * resource.loader.ds.cache = false
+ * resource.loader.ds.modification_check_interval = 60
+ *
+ *

Optionally, the developer can instantiate the DataSourceResourceLoader and set the DataSource via code in + * a manner similar to the following:

+ *
+ *

+ * DataSourceResourceLoader ds = new DataSourceResourceLoader();
+ * ds.setDataSource(DATASOURCE);
+ * Velocity.setProperty("resource.loader.ds.instance",ds);
+ * 
+ *

The property resource.loader.ds.class should be left out, otherwise all the other + * properties in velocity.properties would remain the same.

*
- *
- * Velocity template DataSource
- * jdbc/Velocity
- * javax.sql.DataSource
- * Container
- *

+ *

Example WEB-INF/web.xml:

*
+ *

+ *  <resource-ref>
+ *   <description>Velocity template DataSource</description>
+ *   <res-ref-name>jdbc/Velocity</res-ref-name>
+ *   <res-type>javax.sql.DataSource</res-type>
+ *   <res-auth>Container</res-auth>
+ *  </resource-ref>
+ * 
*
* and Tomcat 4 server.xml file:
- * [...]
- *
- * [...]
- *
- *
- * driverClassName
- * org.hsql.jdbcDriver
- *

- *
- * driverName
- * jdbc:HypersonicSQL:database
- *

- *
- * user
- * database_username
- *

- *
- * password
- * database_password
- *

- *

- * [...]
- *

- * [...]
+ *

+ *  [...]
+ *  <Context path="/exampleVelocity" docBase="exampleVelocity" debug="0">
+ *  [...]
+ *   <ResourceParams name="jdbc/Velocity">
+ *    <parameter>
+ *      <name>driverClassName</name>
+ *      <value>org.hsql.jdbcDriver</value>
+ *    </parameter>
+ *    <parameter>
+ *     <name>driverName</name>
+ *     <value>jdbc:HypersonicSQL:database</value>
+ *    </parameter>
+ *    <parameter>
+ *     <name>user</name>
+ *     <value>database_username</value>
+ *    </parameter>
+ *    <parameter>
+ *     <name>password</name>
+ *     <value>database_password</value>
+ *    </parameter>
+ *   </ResourceParams>
+ *  [...]
+ *  </Context>
+ *  [...]
+ * 
*
- * Example sql script:
- * CREATE TABLE tb_velocity_template (
- * id_template varchar (40) NOT NULL ,
- * template_definition text (16) NOT NULL ,
- * template_timestamp datetime NOT NULL
- * )
+ *

Example sql script:

+ *

+ *  CREATE TABLE tb_velocity_template (
+ *    id_template varchar (40) NOT NULL ,
+ *    template_definition text (16) NOT NULL ,
+ *    template_timestamp datetime NOT NULL
+ *  );
+ * 
* * @author Will Glass-Husain * @author Matt Raible @@ -181,11 +184,11 @@ public class DataSourceResourceLoader extends ResourceLoader */ public void init(ExtProperties configuration) { - dataSourceName = StringUtils.trim(configuration.getString("resource.datasource")); + dataSourceName = StringUtils.trim(configuration.getString("datasource_url")); tableName = StringUtils.trim(configuration.getString("resource.table")); - keyColumn = StringUtils.trim(configuration.getString("resource.keycolumn")); - templateColumn = StringUtils.trim(configuration.getString("resource.templatecolumn")); - timestampColumn = StringUtils.trim(configuration.getString("resource.timestampcolumn")); + keyColumn = StringUtils.trim(configuration.getString("resource.key_column")); + templateColumn = StringUtils.trim(configuration.getString("resource.template_column")); + timestampColumn = StringUtils.trim(configuration.getString("resource.timestamp_column")); if (dataSource != null) { diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/JarResourceLoader.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/JarResourceLoader.java index 8ed76835..bd36f712 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/JarResourceLoader.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/JarResourceLoader.java @@ -46,14 +46,14 @@ import java.util.Map; * You simply add the JarResourceLoader to the configuration via *

*

- *    resource.loader = jar
- *    jar.resource.loader.class = org.apache.velocity.runtime.resource.loader.JarResourceLoader
- *    jar.resource.loader.path = list of JAR <URL>s
+ *    resource.loaders = jar
+ *    resource.loader.jar.class = org.apache.velocity.runtime.resource.loader.JarResourceLoader
+ *    resource.loader.jar.path = list of JAR <URL>s
  * 

* *

So for example, if you had a jar file on your local filesystem, you could simply do *

- *    jar.resource.loader.path = jar:file:/opt/myfiles/jar1.jar
+ *    resource.loader.jar.path = jar:file:/opt/myfiles/jar1.jar
  *    
*

*

Note that jar specification for the .path configuration property diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/StringResourceLoader.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/StringResourceLoader.java index efe72250..9603f826 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/StringResourceLoader.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/StringResourceLoader.java @@ -49,10 +49,11 @@ import java.util.Map; * if not provided, the factory will fall back on using * {@link StringResourceRepositoryImpl} as the default. *

- * resource.loader = string
- * string.resource.loader.description = Velocity StringResource loader
- * string.resource.loader.class = org.apache.velocity.runtime.resource.loader.StringResourceLoader
- * string.resource.loader.repository.class = org.apache.velocity.runtime.resource.loader.StringResourceRepositoryImpl
+ * resource.loaders = string
+ * resource.loader.string.description = Velocity StringResource loader
+ * resource.loader.string.class = org.apache.velocity.runtime.resource.loader.StringResourceLoader
+ * resource.loader.string.repository.name = MyRepositoryName (optional, to avoid using the default repository)
+ * resource.loader.string.repository.class = org.apache.velocity.runtime.resource.loader.StringResourceRepositoryImpl
  * 
* Resources can be added to the repository like this: *

@@ -66,7 +67,7 @@ import java.util.Map;
  * After this, the templates can be retrieved as usual.
  * 
*

If there will be multiple StringResourceLoaders used in an application, - * you should consider specifying a 'string.resource.loader.repository.name = foo' + * you should consider specifying a 'resource.loader.string.repository.name = foo' * property in order to keep you string resources in a non-default repository. * This can help to avoid conflicts between different frameworks or components * that are using StringResourceLoader. @@ -78,7 +79,7 @@ import java.util.Map; *

*

If you have concerns about memory leaks or for whatever reason do not wish * to have your string repository stored statically as a class member, then you - * should set 'string.resource.loader.repository.static = false' in your properties. + * should set 'resource.loader.string.repository.static = false' in your properties. * This will tell the resource loader that the string repository should be stored * in the Velocity application attributes. To retrieve the repository, do: *


@@ -103,7 +104,7 @@ import java.util.Map;
  *   repo.magicallyAddSomeStringResources();
  *   velocityEngine.setApplicationAttribute("foo", repo);
  * 
- * Then, assuming the 'string.resource.loader.repository.name' property is + * Then, assuming the 'resource.loader.string.repository.name' property is * set to 'some.name', the StringResourceLoader will use that already created * repository, rather than creating a new one. *

diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/util/ExtProperties.java b/velocity-engine-core/src/main/java/org/apache/velocity/util/ExtProperties.java index 786f362d..8ae3484c 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/util/ExtProperties.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/util/ExtProperties.java @@ -732,11 +732,11 @@ public class ExtProperties extends DeprecationAwareExtProperties * exists then the value stated here will be added * to the configuration entry. For example, if * - * resource.loader = file + * resource.loaders = file * * is already present in the configuration and you * - * addProperty("resource.loader", "classpath") + * addProperty("resource.loaders", "classpath") * * Then you will end up with a Vector like the * following: diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/LinkingUberspector.java b/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/LinkingUberspector.java index 7a54e2c2..a2130ee9 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/LinkingUberspector.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/LinkingUberspector.java @@ -23,7 +23,7 @@ import java.util.Iterator; /** *

- * When the runtime.introspection.uberspect configuration property contains several + * When the introspector.uberspect.class configuration property contains several * uberspector class names, it means those uberspectors will be chained. When an * uberspector in the list other than the leftmost does not implement ChainableUberspector, * then this utility class is used to provide a basic default chaining where the -- cgit v1.2.3