You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by si...@apache.org on 2011/02/18 23:26:51 UTC
svn commit: r1072175 [1/2] - in
/commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins:
./ strategies/
Author: simonetripodi
Date: Fri Feb 18 22:26:49 2011
New Revision: 1072175
URL: http://svn.apache.org/viewvc?rev=1072175&view=rev
Log:
reintegrated the 'plugin' package, adapted version of the proper one on /trunk
Added:
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/Declaration.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/InitializableRule.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/LogUtils.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginAssertionFailure.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginConfigurationException.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginContext.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginCreateRule.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginDeclarationRule.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginInvalidInputException.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginManager.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginRules.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/RuleFinder.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/RuleLoader.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/RulesFactory.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/package-info.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/strategies/
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/strategies/FinderFromClass.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/strategies/FinderFromDfltClass.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/strategies/FinderFromDfltMethod.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/strategies/FinderFromDfltResource.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/strategies/FinderFromFile.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/strategies/FinderFromMethod.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/strategies/FinderFromResource.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/strategies/FinderSetProperties.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/strategies/LoaderFromClass.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/strategies/LoaderFromStream.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/strategies/LoaderSetProperties.java (with props)
commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/strategies/package-info.java (with props)
Added: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/Declaration.java
URL: http://svn.apache.org/viewvc/commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/Declaration.java?rev=1072175&view=auto
==============================================================================
--- commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/Declaration.java (added)
+++ commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/Declaration.java Fri Feb 18 22:26:49 2011
@@ -0,0 +1,209 @@
+/* $Id$
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.digester3.plugins;
+
+import java.util.Properties;
+
+import org.apache.commons.digester3.Digester;
+import org.apache.commons.logging.Log;
+
+/**
+ * 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.
+ */
+public class Declaration {
+
+ /** The class of the object to be instantiated. */
+ private Class<?> pluginClass;
+
+ /** The name of the class of the object to be instantiated. */
+ private String pluginClassName;
+
+ /** See {@link #setId}. */
+ private String id;
+
+ /** See {@link #setProperties}. */
+ private Properties properties = new Properties();
+
+ /** See {@link #init}. */
+ private boolean initialized = false;
+
+ /**
+ * Class which is responsible for dynamically loading this
+ * plugin's rules on demand.
+ */
+ private RuleLoader ruleLoader = null;
+
+ //---------------------- constructors ----------------------------------
+
+ /**
+ * Constructor.
+ */
+ public Declaration(String pluginClassName) {
+ // We can't load the pluginClass at this time, because we don't
+ // have a digester instance yet to load it through. So just
+ // save the name away, and we'll load the Class object in the
+ // init method.
+ this.pluginClassName = pluginClassName;
+ }
+
+ /**
+ * Constructor.
+ */
+ public Declaration(Class<?> pluginClass) {
+ this(pluginClass.getName());
+ this.pluginClass = pluginClass;
+ }
+
+ /**
+ * Create an instance where a fully-initialised ruleLoader instance
+ * is provided by the caller instead of having the PluginManager
+ * "discover" an appropriate one.
+ */
+ public Declaration(Class<?> pluginClass, RuleLoader ruleLoader) {
+ this(pluginClass);
+ this.ruleLoader = ruleLoader;
+ }
+
+ /**
+ * The id that the user associated with a particular plugin declaration
+ * in the input xml. This id is later used in the input xml to refer
+ * back to the original declaration.
+ * <p>
+ * For plugins declared "in-line", the id is null.
+ */
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ /**
+ * Return the id associated with this declaration. For plugins
+ * declared "inline", null will be returned.
+ *
+ * @return The id value. May be null.
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Copy all (key,value) pairs in the param into the properties member of
+ * this object.
+ * <p>
+ * The declaration properties cannot be explicit member variables,
+ * because the set of useful properties a user can provide on a declaration
+ * depends on what RuleFinder classes are available - and extra RuleFinders
+ * can be added by the user. So here we keep a map of the settings, and
+ * let the RuleFinder objects look for whatever properties they consider
+ * significant.
+ * <p>
+ * The "id" and "class" properties are treated differently.
+ */
+ public void setProperties(Properties p) {
+ properties.putAll(p);
+ }
+
+ /**
+ * Return plugin class associated with this declaration.
+ *
+ * @return The pluginClass.
+ */
+ public Class<?> getPluginClass() {
+ return pluginClass;
+ }
+
+ /**
+ * Must be called exactly once, and must be called before any call
+ * to the configure method.
+ */
+ public void init(Digester digester, PluginManager pm) throws PluginException {
+ Log log = digester.getLog();
+ boolean debug = log.isDebugEnabled();
+ if (debug) {
+ log.debug("init being called!");
+ }
+
+ if (initialized) {
+ throw new PluginAssertionFailure("Init called multiple times.");
+ }
+
+ if ((pluginClass == null) && (pluginClassName != null)) {
+ try {
+ // load the plugin class object
+ pluginClass =
+ digester.getClassLoader().loadClass(pluginClassName);
+ } catch(ClassNotFoundException cnfe) {
+ throw new PluginException(
+ "Unable to load class " + pluginClassName, cnfe);
+ }
+ }
+
+ if (ruleLoader == null) {
+ // the caller didn't provide a ruleLoader to the constructor,
+ // so get the plugin manager to "discover" one.
+ log.debug("Searching for ruleloader...");
+ ruleLoader = pm.findLoader(digester, id, pluginClass, properties);
+ } else {
+ log.debug("This declaration has an explicit ruleLoader.");
+ }
+
+ if (debug) {
+ if (ruleLoader == null) {
+ log.debug(
+ "No ruleLoader found for plugin declaration"
+ + " id [" + id + "]"
+ + ", class [" + pluginClass.getClass().getName() + "].");
+ } else {
+ log.debug(
+ "RuleLoader of type [" + ruleLoader.getClass().getName()
+ + "] associated with plugin declaration"
+ + " id [" + id + "]"
+ + ", class [" + pluginClass.getClass().getName() + "].");
+ }
+ }
+
+ initialized = true;
+ }
+
+ /**
+ * Attempt to load custom rules for the target class at the specified
+ * pattern.
+ * <p>
+ * On return, any custom rules associated with the plugin class have
+ * been loaded into the Rules object currently associated with the
+ * specified digester object.
+ */
+
+ public void configure(Digester digester, String pattern) throws PluginException {
+ Log log = digester.getLog();
+ boolean debug = log.isDebugEnabled();
+ if (debug) {
+ log.debug("configure being called!");
+ }
+
+ if (!initialized) {
+ throw new PluginAssertionFailure("Not initialized.");
+ }
+
+ if (ruleLoader != null) {
+ ruleLoader.addRules(digester, pattern);
+ }
+ }
+
+}
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/Declaration.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/Declaration.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/Declaration.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/InitializableRule.java
URL: http://svn.apache.org/viewvc/commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/InitializableRule.java?rev=1072175&view=auto
==============================================================================
--- commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/InitializableRule.java (added)
+++ commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/InitializableRule.java Fri Feb 18 22:26:49 2011
@@ -0,0 +1,40 @@
+/* $Id$
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.digester3.plugins;
+
+/**
+ * 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.
+ */
+public interface InitializableRule {
+
+ /**
+ * Called after this Rule object has been added to the list of all Rules.
+ * Note that if a single InitializableRule instance is associated with
+ * more than one pattern, then this method will be called more than once.
+ *
+ * @param pattern is the digester match pattern that will trigger this
+ * rule.
+ * @exception
+ * PluginConfigurationException is thrown if the InitializableRule
+ * determines that it cannot correctly initialise itself for any reason.
+ */
+ void postRegisterInit(String pattern) throws PluginConfigurationException;
+
+}
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/InitializableRule.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/InitializableRule.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/InitializableRule.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/LogUtils.java
URL: http://svn.apache.org/viewvc/commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/LogUtils.java?rev=1072175&view=auto
==============================================================================
--- commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/LogUtils.java (added)
+++ commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/LogUtils.java Fri Feb 18 22:26:49 2011
@@ -0,0 +1,71 @@
+/* $Id$
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.digester3.plugins;
+
+import org.apache.commons.digester3.Digester;
+import org.apache.commons.logging.Log;
+
+/**
+ * Simple utility class to assist in logging.
+ * <p>
+ * This class is intended only for the use of the code in the
+ * plugins packages. No "user" code should use this package.
+ * <p>
+ * The Digester module has an interesting approach to logging:
+ * all logging should be done via the Log object stored on the
+ * digester instance that the object *doing* the logging is associated
+ * with.
+ * <p>
+ * This is done because apparently some "container"-type applications
+ * such as Avalon and Tomcat need to be able to configure different logging
+ * for different <i>instances</i> of the Digester class which have been
+ * loaded from the same ClassLoader [info from Craig McClanahan].
+ * Not only the logging of the Digester instance should be affected; all
+ * objects associated with that Digester instance should obey the
+ * reconfiguration of their owning Digester instance's logging. The current
+ * solution is to force all objects to output logging info via a single
+ * Log object stored on the Digester instance they are associated with.
+ * <p>
+ * Of course this causes problems if logging is attempted before an
+ * object <i>has</i> a valid reference to its owning Digester. The
+ * getLogging method provided here resolves this issue by returning a
+ * Log object which silently discards all logging output in this
+ * situation.
+ * <p>
+ * And it also implies that logging filtering can no longer be applied
+ * to subcomponents of the Digester, because all logging is done via
+ * a single Log object (a single Category). C'est la vie...
+ */
+class LogUtils {
+
+ /**
+ * Get the Log object associated with the specified Digester instance,
+ * or a "no-op" logging object if the digester reference is null.
+ * <p>
+ * You should use this method instead of digester.getLogger() in
+ * any situation where the digester might be null.
+ */
+ static Log getLogger(Digester digester) {
+ if (digester == null) {
+ return new org.apache.commons.logging.impl.NoOpLog();
+ }
+
+ return digester.getLog();
+ }
+
+}
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/LogUtils.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/LogUtils.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/LogUtils.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginAssertionFailure.java
URL: http://svn.apache.org/viewvc/commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginAssertionFailure.java?rev=1072175&view=auto
==============================================================================
--- commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginAssertionFailure.java (added)
+++ commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginAssertionFailure.java Fri Feb 18 22:26:49 2011
@@ -0,0 +1,71 @@
+/* $Id$
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.digester3.plugins;
+
+/**
+ * Thrown when a bug is detected in the plugins code.
+ * <p>
+ * This class is intended to be used in assertion statements, similar to
+ * the way that java 1.4's native assertion mechanism is used. However there
+ * is a difference: when a java 1.4 assertion fails, an AssertionError
+ * is thrown, which is a subclass of Error; here, the PluginAssertionFailure
+ * class extends RuntimeException rather than Error.
+ * <p>
+ * This difference in design is because throwing Error objects is not
+ * good in a container-based architecture.
+ * <p>
+ * Example:
+ * <pre>
+ * if (impossibleCondition) {
+ * throw new PluginAssertionFailure(
+ * "internal error: impossible condition is true");
+ * }
+ * </pre>
+ * <p>
+ * Note that PluginAssertionFailure should <i>not</i> be thrown when user
+ * input is bad, or when code external to the Digester module passes invalid
+ * parameters to a plugins method. It should be used only in checks for
+ * problems which indicate internal bugs within the plugins module.
+ */
+public class PluginAssertionFailure extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * @param cause underlying exception that caused this to be thrown
+ */
+ public PluginAssertionFailure(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * @param msg describes the reason this exception is being thrown.
+ */
+ public PluginAssertionFailure(String msg) {
+ super(msg);
+ }
+
+ /**
+ * @param msg describes the reason this exception is being thrown.
+ * @param cause underlying exception that caused this to be thrown
+ */
+ public PluginAssertionFailure(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+}
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginAssertionFailure.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginAssertionFailure.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginAssertionFailure.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginConfigurationException.java
URL: http://svn.apache.org/viewvc/commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginConfigurationException.java?rev=1072175&view=auto
==============================================================================
--- commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginConfigurationException.java (added)
+++ commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginConfigurationException.java Fri Feb 18 22:26:49 2011
@@ -0,0 +1,53 @@
+/* $Id$
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.digester3.plugins;
+
+/**
+ * Thrown when an error occurs due to the way the calling application uses
+ * the plugins module. Because the pre-existing Digester API doesn't provide
+ * any option for throwing checked exceptions at some points where Plugins
+ * can potentially fail, this exception extends RuntimeException so that it
+ * can "tunnel" through these points.
+ */
+public class PluginConfigurationException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * @param cause underlying exception that caused this to be thrown
+ */
+ public PluginConfigurationException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * @param msg describes the reason this exception is being thrown.
+ */
+ public PluginConfigurationException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * @param msg describes the reason this exception is being thrown.
+ * @param cause underlying exception that caused this to be thrown
+ */
+ public PluginConfigurationException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+}
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginConfigurationException.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginConfigurationException.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginConfigurationException.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginContext.java
URL: http://svn.apache.org/viewvc/commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginContext.java?rev=1072175&view=auto
==============================================================================
--- commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginContext.java (added)
+++ commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginContext.java Fri Feb 18 22:26:49 2011
@@ -0,0 +1,239 @@
+/* $Id$
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.digester3.plugins;
+
+import java.util.List;
+import java.util.LinkedList;
+
+import org.apache.commons.digester3.plugins.strategies.FinderFromFile;
+import org.apache.commons.digester3.plugins.strategies.FinderFromResource;
+import org.apache.commons.digester3.plugins.strategies.FinderFromClass;
+import org.apache.commons.digester3.plugins.strategies.FinderFromMethod;
+import org.apache.commons.digester3.plugins.strategies.FinderFromDfltMethod;
+import org.apache.commons.digester3.plugins.strategies.FinderFromDfltClass;
+import org.apache.commons.digester3.plugins.strategies.FinderFromDfltResource;
+import org.apache.commons.digester3.plugins.strategies.FinderSetProperties;
+
+/**
+ * Provides data and services which should exist only once per digester.
+ * <p>
+ * This class holds a number of useful items which should be shared by all
+ * plugin objects. Such data cannot be stored on the PluginRules or
+ * PluginManager classes, as there can be multiple instances of these at
+ * various times during a parse.
+ * <p>
+ * The name "Context" refers to the similarity between this class and a
+ * ServletContext class in a servlet engine. A ServletContext object provides
+ * access to the container's services such as obtaining global configuration
+ * parameters for the container, or getting access to logging services. For
+ * plugins, a Digester instance can be regarded as "the container".
+ */
+public class PluginContext {
+
+ // TODO: Consider making following four constants static in 2.0
+ // the xml attribute the user uses on an xml element to specify
+ // the plugin's class
+ public final String DFLT_PLUGIN_CLASS_ATTR_NS = null;
+
+ public final String DFLT_PLUGIN_CLASS_ATTR = "plugin-class";
+
+ // the xml attribute the user uses on an xml element to specify
+ // the plugin's class
+ public final String DFLT_PLUGIN_ID_ATTR_NS = null;
+
+ public final String DFLT_PLUGIN_ID_ATTR = "plugin-id";
+
+ /** See {@link #setPluginClassAttribute}. */
+ private String pluginClassAttrNs = DFLT_PLUGIN_CLASS_ATTR_NS;
+
+ /** See {@link #setPluginClassAttribute}. */
+ private String pluginClassAttr = DFLT_PLUGIN_CLASS_ATTR;
+
+ /** See {@link #setPluginClassAttribute}. */
+ private String pluginIdAttrNs = DFLT_PLUGIN_ID_ATTR_NS;
+
+ /** See {@link #setPluginClassAttribute}. */
+ private String pluginIdAttr = DFLT_PLUGIN_ID_ATTR;
+
+ /**
+ * A list of RuleFinder objects used by all Declarations (and thus
+ * indirectly by all PluginCreateRules to locate the custom rules
+ * for plugin classes.
+ */
+ private List<RuleFinder> ruleFinders;
+
+ /**
+ * Return the list of RuleFinder objects. Under normal circumstances
+ * this method creates a default list of these objects when first called
+ * (ie "on-demand" or "lazy initialization"). However if setRuleFinders
+ * has been called first, then the list specified there is returned.
+ * <p>
+ * It is explicitly permitted for the caller to modify this list
+ * by inserting or removing RuleFinder objects.
+ */
+ public List<RuleFinder> getRuleFinders() {
+ if (ruleFinders == null) {
+ // when processing a plugin declaration, attempts are made to
+ // find custom rules in the order in which the Finder objects
+ // are added below. However this list can be modified
+ ruleFinders = new LinkedList<RuleFinder>();
+ ruleFinders.add(new FinderFromFile());
+ ruleFinders.add(new FinderFromResource());
+ ruleFinders.add(new FinderFromClass());
+ ruleFinders.add(new FinderFromMethod());
+ ruleFinders.add(new FinderFromDfltMethod());
+ ruleFinders.add(new FinderFromDfltClass());
+ ruleFinders.add(new FinderFromDfltResource());
+ ruleFinders.add(new FinderFromDfltResource(".xml"));
+ ruleFinders.add(new FinderSetProperties());
+ }
+ return ruleFinders;
+ }
+
+ /**
+ * Set the list of RuleFinder objects. This may be useful if working
+ * in a non-english language, allowing the application developer to
+ * replace the standard list with a list of objects which look for xml
+ * attributes in the local language.
+ * <p>
+ * If the intent is just to add an additional rule-finding algorithm, then
+ * it may be better to call #getRuleFinders, and insert a new object into
+ * the start of the list.
+ */
+ public void setRuleFinders(List<RuleFinder> ruleFinders) {
+ this.ruleFinders = ruleFinders;
+ }
+
+ /**
+ * Sets the xml attribute which the input xml uses to indicate to a
+ * PluginCreateRule which class should be instantiated.
+ * <p>
+ * Example:
+ * <pre>
+ * setPluginClassAttribute(null, "class");
+ * </pre>
+ * will allow this in the input xml:
+ * <pre>
+ * <root>
+ * <some-plugin class="com.acme.widget"> ......
+ * </pre>
+ * instead of the default syntax:
+ * <pre>
+ * <root>
+ * <some-plugin plugin-class="com.acme.widget"> ......
+ * </pre>
+ * This is particularly useful if the input xml document is not in
+ * English.
+ * <p>
+ * Note that the xml attributes used by PluginDeclarationRules are not
+ * affected by this method.
+ *
+ * @param namespaceUri is the namespace uri that the specified attribute
+ * is in. If the attribute is in no namespace, then this should be null.
+ * Note that if a namespace is used, the attrName value should <i>not</i>
+ * contain any kind of namespace-prefix. Note also that if you are using
+ * a non-namespace-aware parser, this parameter <i>must</i> be null.
+ *
+ * @param attrName is the attribute whose value contains the name of the
+ * class to be instantiated.
+ */
+ public void setPluginClassAttribute(String namespaceUri,
+ String attrName) {
+ pluginClassAttrNs = namespaceUri;
+ pluginClassAttr = attrName;
+ }
+
+ /**
+ * Sets the xml attribute which the input xml uses to indicate to a
+ * PluginCreateRule which plugin declaration is being referenced.
+ * <p>
+ * Example:
+ * <pre>
+ * setPluginIdAttribute(null, "id");
+ * </pre>
+ * will allow this in the input xml:
+ * <pre>
+ * <root>
+ * <some-plugin id="widget"> ......
+ * </pre>
+ * rather than the default behaviour:
+ * <pre>
+ * <root>
+ * <some-plugin plugin-id="widget"> ......
+ * </pre>
+ * This is particularly useful if the input xml document is not in
+ * English.
+ * <p>
+ * Note that the xml attributes used by PluginDeclarationRules are not
+ * affected by this method.
+ *
+ * @param namespaceUri is the namespace uri that the specified attribute
+ * is in. If the attribute is in no namespace, then this should be null.
+ * Note that if a namespace is used, the attrName value should <i>not</i>
+ * contain any kind of namespace-prefix. Note also that if you are using
+ * a non-namespace-aware parser, this parameter <i>must</i> be null.
+ *
+ * @param attrName is the attribute whose value contains the id of the
+ * plugin declaration to be used when instantiating an object.
+ */
+ public void setPluginIdAttribute(String namespaceUri,
+ String attrName) {
+ pluginIdAttrNs = namespaceUri;
+ pluginIdAttr = attrName;
+ }
+
+ /**
+ * Get the namespace for the xml attribute which indicates to a
+ * PluginCreateRule which class is to be plugged in.
+ * <p>
+ * May be null (in fact, normally will be).
+ */
+ public String getPluginClassAttrNs() {
+ return pluginClassAttrNs;
+ }
+
+ /**
+ * Get the namespace for the xml attribute which indicates to a
+ * PluginCreateRule which class is to be plugged in.
+ * <p>
+ * The return value is never null.
+ */
+ public String getPluginClassAttr() {
+ return pluginClassAttr;
+ }
+
+ /**
+ * Get the namespace for the xml attribute which indicates to a
+ * PluginCreateRule which previous plugin declaration should be used.
+ * <p>
+ * May be null (in fact, normally will be).
+ */
+ public String getPluginIdAttrNs() {
+ return pluginIdAttrNs;
+ }
+
+ /**
+ * Get the namespace for the xml attribute which indicates to a
+ * PluginCreateRule which previous plugin declaration should be used.
+ * <p>
+ * The return value is never null.
+ */
+ public String getPluginIdAttr() {
+ return pluginIdAttr;
+ }
+}
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginContext.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginContext.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginContext.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginCreateRule.java
URL: http://svn.apache.org/viewvc/commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginCreateRule.java?rev=1072175&view=auto
==============================================================================
--- commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginCreateRule.java (added)
+++ commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginCreateRule.java Fri Feb 18 22:26:49 2011
@@ -0,0 +1,571 @@
+/* $Id$
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.digester3.plugins;
+
+import java.util.List;
+
+import org.apache.commons.digester3.Rule;
+import org.apache.commons.logging.Log;
+import org.xml.sax.Attributes;
+
+/**
+ * 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.
+ */
+public class PluginCreateRule extends Rule implements InitializableRule {
+
+ // see setPluginClassAttribute
+ private String pluginClassAttrNs = null;
+
+ private String pluginClassAttr = null;
+
+ // see setPluginIdAttribute
+ private String pluginIdAttrNs = null;
+
+ private String pluginIdAttr = null;
+
+ /**
+ * In order to invoke the addRules method on the plugin class correctly,
+ * we need to know the pattern which this rule is matched by.
+ */
+ private String pattern;
+
+ /** A base class that any plugin must derive from. */
+ private Class<?> baseClass = null;
+
+ /**
+ * Info about optional default plugin to be used if no plugin-id is
+ * specified in the input data. This can simplify the syntax where one
+ * particular plugin is usually used.
+ */
+ private Declaration defaultPlugin;
+
+ /**
+ * Currently, none of the Rules methods allow exceptions to be thrown.
+ * Therefore if this class cannot initialise itself properly, it cannot
+ * cause the digester to stop. Instead, we cache the exception and throw
+ * it the first time the begin() method is called.
+ */
+ private PluginConfigurationException initException;
+
+ /**
+ * Create a plugin rule where the user <i>must</i> specify a plugin-class
+ * or plugin-id.
+ *
+ * @param baseClass is the class which any specified plugin <i>must</i> be
+ * descended from.
+ */
+ public PluginCreateRule(Class<?> baseClass) {
+ this.baseClass = baseClass;
+ }
+
+ /**
+ * Create a plugin rule where the user <i>may</i> specify a plugin.
+ * If the user doesn't specify a plugin, then the default class specified
+ * in this constructor is used.
+ *
+ * @param baseClass is the class which any specified plugin <i>must</i> be
+ * descended from.
+ * @param dfltPluginClass is the class which will be used if the user
+ * doesn't specify any plugin-class or plugin-id. This class will have
+ * custom rules installed for it just like a declared plugin.
+ */
+ public PluginCreateRule(Class<?> baseClass, Class<?> dfltPluginClass) {
+ this.baseClass = baseClass;
+ if (dfltPluginClass != null) {
+ defaultPlugin = new Declaration(dfltPluginClass);
+ }
+ }
+
+ /**
+ * Create a plugin rule where the user <i>may</i> specify a plugin.
+ * If the user doesn't specify a plugin, then the default class specified
+ * in this constructor is used.
+ *
+ * @param baseClass is the class which any specified plugin <i>must</i> be
+ * descended from.
+ * @param dfltPluginClass is the class which will be used if the user
+ * doesn't specify any plugin-class or plugin-id. This class will have
+ * custom rules installed for it just like a declared plugin.
+ * @param dfltPluginRuleLoader is a RuleLoader instance which knows how
+ * to load the custom rules associated with this default plugin.
+ */
+ public PluginCreateRule(Class<?> baseClass, Class<?> dfltPluginClass, RuleLoader dfltPluginRuleLoader) {
+ this.baseClass = baseClass;
+ if (dfltPluginClass != null) {
+ defaultPlugin =
+ new Declaration(dfltPluginClass, dfltPluginRuleLoader);
+ }
+ }
+
+ /**
+ * Sets the xml attribute which the input xml uses to indicate to a
+ * PluginCreateRule which class should be instantiated.
+ * <p>
+ * See {@link PluginRules#setPluginClassAttribute} for more info.
+ */
+ public void setPluginClassAttribute(String namespaceUri, String attrName) {
+ pluginClassAttrNs = namespaceUri;
+ pluginClassAttr = attrName;
+ }
+
+ /**
+ * Sets the xml attribute which the input xml uses to indicate to a
+ * PluginCreateRule which plugin declaration is being referenced.
+ * <p>
+ * See {@link PluginRules#setPluginIdAttribute} for more info.
+ */
+ public void setPluginIdAttribute(String namespaceUri, String attrName) {
+ pluginIdAttrNs = namespaceUri;
+ pluginIdAttr = attrName;
+ }
+
+ /**
+ * Invoked after this rule has been added to the set of digester rules,
+ * associated with the specified pattern. Check all configuration data is
+ * valid and remember the pattern for later.
+ *
+ * @param matchPattern is the digester match pattern that is associated
+ * with this rule instance, eg "root/widget".
+ * @exception PluginConfigurationException
+ */
+ public void postRegisterInit(String matchPattern) throws PluginConfigurationException {
+ Log log = LogUtils.getLogger(this.getDigester());
+ boolean debug = log.isDebugEnabled();
+ if (debug) {
+ log.debug("PluginCreateRule.postRegisterInit" +
+ ": rule registered for pattern [" + matchPattern + "]");
+ }
+
+ if (this.getDigester() == null) {
+ // We require setDigester to be called before this method.
+ // Note that this means that PluginCreateRule cannot be added
+ // to a Rules object which has not yet been added to a
+ // Digester object.
+ initException = new PluginConfigurationException("Invalid invocation of postRegisterInit"
+ + ": digester not set.");
+ throw initException;
+ }
+
+ if (pattern != null) {
+ // We have been called twice, ie a single instance has been
+ // associated with multiple patterns.
+ //
+ // Generally, Digester Rule instances can be associated with
+ // multiple patterns. However for plugins, this creates some
+ // complications. Some day this may be supported; however for
+ // now we just reject this situation.
+ initException = new PluginConfigurationException("A single PluginCreateRule instance has been mapped to"
+ + " multiple patterns; this is not supported.");
+ throw initException;
+ }
+
+ if (matchPattern.indexOf('*') != -1) {
+ // having wildcards in patterns is extremely difficult to
+ // deal with. For now, we refuse to allow this.
+ //
+ // TODO: check for any chars not valid in xml element name
+ // rather than just *.
+ //
+ // Reasons include:
+ // (a) handling recursive plugins, and
+ // (b) determining whether one pattern is "below" another,
+ // as done by PluginRules. Without wildcards, "below"
+ // just means startsWith, which is easy to check.
+ initException = new PluginConfigurationException(
+ "A PluginCreateRule instance has been mapped to" +
+ " pattern [" + matchPattern + "]." +
+ " This pattern includes a wildcard character." +
+ " This is not supported by the plugin architecture.");
+ throw initException;
+ }
+
+ if (baseClass == null) {
+ baseClass = Object.class;
+ }
+
+ PluginRules rules = (PluginRules) this.getDigester().getRules();
+ PluginManager pm = rules.getPluginManager();
+
+ // check default class is valid
+ if (defaultPlugin != null) {
+ if (!baseClass.isAssignableFrom(defaultPlugin.getPluginClass())) {
+ initException = new PluginConfigurationException("Default class ["
+ + defaultPlugin.getPluginClass().getName()
+ + "] does not inherit from ["
+ + baseClass.getName()
+ + "].");
+ throw initException;
+ }
+
+ try {
+ defaultPlugin.init(this.getDigester(), pm);
+ } catch(PluginException pwe) {
+ throw new PluginConfigurationException(pwe.getMessage(), pwe.getCause());
+ }
+ }
+
+ // remember the pattern for later
+ pattern = matchPattern;
+
+ if (pluginClassAttr == null) {
+ // the user hasn't set explicit xml attr names on this rule,
+ // so fetch the default values
+ pluginClassAttrNs = rules.getPluginClassAttrNs();
+ pluginClassAttr = rules.getPluginClassAttr();
+
+ if (debug) {
+ log.debug("init: pluginClassAttr set to per-digester values ["
+ + "ns="
+ + pluginClassAttrNs
+ + ", name="
+ + pluginClassAttr
+ + "]");
+ }
+ } else {
+ if (debug) {
+ log.debug(
+ "init: pluginClassAttr set to rule-specific values ["
+ + "ns="
+ + pluginClassAttrNs
+ + ", name="
+ + pluginClassAttr
+ + "]");
+ }
+ }
+
+ if (pluginIdAttr == null) {
+ // the user hasn't set explicit xml attr names on this rule,
+ // so fetch the default values
+ pluginIdAttrNs = rules.getPluginIdAttrNs();
+ pluginIdAttr = rules.getPluginIdAttr();
+
+ if (debug) {
+ log.debug(
+ "init: pluginIdAttr set to per-digester values ["
+ + "ns="
+ + pluginIdAttrNs
+ + ", name="
+ + pluginIdAttr
+ + "]");
+ }
+ } else {
+ if (debug) {
+ log.debug(
+ "init: pluginIdAttr set to rule-specific values ["
+ + "ns="
+ + pluginIdAttrNs
+ + ", name="
+ + pluginIdAttr
+ + "]");
+ }
+ }
+ }
+
+ /**
+ * Invoked when the Digester matches this rule against an xml element.
+ * <p>
+ * A new instance of the target class is created, and pushed onto the
+ * stack. A new "private" PluginRules object is then created and set as
+ * the digester's default Rules object. Any custom rules associated with
+ * the plugin class are then loaded into that new Rules object.
+ * Finally, any custom rules that are associated with the current pattern
+ * (such as SetPropertiesRules) have their begin methods executed.
+ *
+ * @param namespace
+ * @param name
+ * @param attributes
+ *
+ * @throws ClassNotFoundException
+ * @throws PluginInvalidInputException
+ * @throws PluginConfigurationException
+ */
+ @Override
+ public void begin(String namespace, String name,
+ org.xml.sax.Attributes attributes)
+ throws java.lang.Exception {
+ Log log = this.getDigester().getLog();
+ boolean debug = log.isDebugEnabled();
+ if (debug) {
+ log.debug("PluginCreateRule.begin" + ": pattern=[" + pattern + "]" +
+ " match=[" + this.getDigester().getMatch() + "]");
+ }
+
+ if (initException != null) {
+ // we had a problem during initialisation that we could
+ // not report then; report it now.
+ throw initException;
+ }
+
+ // load any custom rules associated with the plugin
+ PluginRules oldRules = (PluginRules) this.getDigester().getRules();
+ PluginManager pluginManager = oldRules.getPluginManager();
+ Declaration currDeclaration = null;
+
+ String pluginClassName;
+ if (pluginClassAttrNs == null) {
+ // Yep, this is ugly.
+ //
+ // In a namespace-aware parser, the one-param version will
+ // return attributes with no namespace.
+ //
+ // In a non-namespace-aware parser, the two-param version will
+ // never return any attributes, ever.
+ pluginClassName = attributes.getValue(pluginClassAttr);
+ } else {
+ pluginClassName =
+ attributes.getValue(pluginClassAttrNs, pluginClassAttr);
+ }
+
+ String pluginId;
+ if (pluginIdAttrNs == null) {
+ pluginId = attributes.getValue(pluginIdAttr);
+ } else {
+ pluginId =
+ attributes.getValue(pluginIdAttrNs, pluginIdAttr);
+ }
+
+ if (pluginClassName != null) {
+ // The user is using a plugin "inline", ie without a previous
+ // explicit declaration. If they have used the same plugin class
+ // before, we have already gone to the effort of creating a
+ // Declaration object, so retrieve it. If there is no existing
+ // declaration object for this class, then create one.
+
+ currDeclaration = pluginManager.getDeclarationByClass(
+ pluginClassName);
+
+ if (currDeclaration == null) {
+ currDeclaration = new Declaration(pluginClassName);
+ try {
+ currDeclaration.init(this.getDigester(), pluginManager);
+ } catch(PluginException pwe) {
+ throw new PluginInvalidInputException(
+ pwe.getMessage(), pwe.getCause());
+ }
+ pluginManager.addDeclaration(currDeclaration);
+ }
+ } else if (pluginId != null) {
+ currDeclaration = pluginManager.getDeclarationById(pluginId);
+
+ if (currDeclaration == null) {
+ throw new PluginInvalidInputException(
+ "Plugin id [" + pluginId + "] is not defined.");
+ }
+ } else if (defaultPlugin != null) {
+ currDeclaration = defaultPlugin;
+ } else {
+ throw new PluginInvalidInputException(
+ "No plugin class specified for element " +
+ pattern);
+ }
+
+ // get the class of the user plugged-in type
+ Class<?> pluginClass = currDeclaration.getPluginClass();
+
+ String path = this.getDigester().getMatch();
+
+ // create a new Rules object and effectively push it onto a stack of
+ // rules objects. The stack is actually a linked list; using the
+ // PluginRules constructor below causes the new instance to link
+ // to the previous head-of-stack, then the Digester.setRules() makes
+ // the new instance the new head-of-stack.
+ PluginRules newRules = new PluginRules(this.getDigester(), path, oldRules, pluginClass);
+ this.getDigester().setRules(newRules);
+
+ if (debug) {
+ log.debug("PluginCreateRule.begin: installing new plugin: " +
+ "oldrules=" + oldRules.toString() +
+ ", newrules=" + newRules.toString());
+ }
+
+ // load up the custom rules
+ currDeclaration.configure(this.getDigester(), pattern);
+
+ // create an instance of the plugin class
+ Object instance = pluginClass.newInstance();
+ getDigester().push(instance);
+ if (debug) {
+ log.debug(
+ "PluginCreateRule.begin" + ": pattern=[" + pattern + "]" +
+ " match=[" + this.getDigester().getMatch() + "]" +
+ " pushed instance of plugin [" + pluginClass.getName() + "]");
+ }
+
+ // and now we have to fire any custom rules which would have
+ // been matched by the same path that matched this rule, had
+ // they been loaded at that time.
+ List<Rule> rules = newRules.getDecoratedRules().match(namespace, path);
+ fireBeginMethods(rules, namespace, name, attributes);
+ }
+
+ /**
+ * Process the body text of this element.
+ *
+ * @param text The body text of this element
+ */
+ @Override
+ public void body(String namespace, String name, String text) throws Exception {
+ // While this class itself has no work to do in the body method,
+ // we do need to fire the body methods of all dynamically-added
+ // rules matching the same path as this rule. During begin, we had
+ // to manually execute the dynamic rules' begin methods because they
+ // didn't exist in the digester's Rules object when the match begin.
+ // So in order to ensure consistent ordering of rule execution, the
+ // PluginRules class deliberately avoids returning any such rules
+ // in later calls to the match method, instead relying on this
+ // object to execute them at the appropriate time.
+ //
+ // Note that this applies only to rules matching exactly the path
+ // which is also matched by this PluginCreateRule.
+
+ String path = this.getDigester().getMatch();
+ PluginRules newRules = (PluginRules) this.getDigester().getRules();
+ List<Rule> rules = newRules.getDecoratedRules().match(namespace, path);
+ fireBodyMethods(rules, namespace, name, text);
+ }
+
+ /**
+ * Invoked by the digester when the closing tag matching this Rule's
+ * pattern is encountered.
+ * </p>
+ *
+ * @param namespace Description of the Parameter
+ * @param name Description of the Parameter
+ * @exception Exception Description of the Exception
+ *
+ * @see #begin
+ */
+ @Override
+ public void end(String namespace, String name) throws Exception {
+ // see body method for more info
+ String path = this.getDigester().getMatch();
+ PluginRules newRules = (PluginRules) this.getDigester().getRules();
+ List<Rule> rules = newRules.getDecoratedRules().match(namespace, path);
+ fireEndMethods(rules, namespace, name);
+
+ // pop the stack of PluginRules instances, which
+ // discards all custom rules associated with this plugin
+ this.getDigester().setRules(newRules.getParent());
+
+ // and get rid of the instance of the plugin class from the
+ // digester object stack.
+ this.getDigester().pop();
+ }
+
+ /**
+ * Return the pattern that this Rule is associated with.
+ * <p>
+ * In general, Rule instances <i>can</i> be associated with multiple
+ * patterns. A PluginCreateRule, however, will only function correctly
+ * when associated with a single pattern. It is possible to fix this, but
+ * I can't be bothered just now because this feature is unlikely to be
+ * used.
+ * </p>
+ *
+ * @return The pattern value
+ */
+ public String getPattern() {
+ return pattern;
+ }
+
+ /**
+ * Duplicate the processing that the Digester does when firing the
+ * begin methods of rules. It would be really nice if the Digester
+ * class provided a way for this functionality to just be invoked
+ * directly.
+ */
+ public void fireBeginMethods(List<Rule> rules,
+ String namespace,
+ String name,
+ Attributes list) throws Exception {
+ if ((rules != null) && (rules.size() > 0)) {
+ Log log = this.getDigester().getLog();
+ boolean debug = log.isDebugEnabled();
+ for (int i = 0; i < rules.size(); i++) {
+ try {
+ Rule rule = rules.get(i);
+ if (debug) {
+ log.debug(" Fire begin() for " + rule);
+ }
+ rule.begin(namespace, name, list);
+ } catch (Exception e) {
+ throw this.getDigester().createSAXException(e);
+ } catch (Error e) {
+ throw e;
+ }
+ }
+ }
+ }
+
+ /**
+ * Duplicate the processing that the Digester does when firing the
+ * body methods of rules. It would be really nice if the Digester
+ * class provided a way for this functionality to just be invoked
+ * directly.
+ */
+ private void fireBodyMethods(List<Rule> rules, String namespaceURI, String name, String text) throws Exception {
+ if ((rules != null) && (rules.size() > 0)) {
+ Log log = this.getDigester().getLog();
+ boolean debug = log.isDebugEnabled();
+ for (int i = 0; i < rules.size(); i++) {
+ try {
+ Rule rule = rules.get(i);
+ if (debug) {
+ log.debug(" Fire body() for " + rule);
+ }
+ rule.body(namespaceURI, name, text);
+ } catch (Exception e) {
+ throw this.getDigester().createSAXException(e);
+ } catch (Error e) {
+ throw e;
+ }
+ }
+ }
+ }
+
+ /**
+ * Duplicate the processing that the Digester does when firing the
+ * end methods of rules. It would be really nice if the Digester
+ * class provided a way for this functionality to just be invoked
+ * directly.
+ */
+ public void fireEndMethods(List<Rule> rules, String namespaceURI, String name) throws Exception {
+ // Fire "end" events for all relevant rules in reverse order
+ if (rules != null) {
+ Log log = this.getDigester().getLog();
+ boolean debug = log.isDebugEnabled();
+ for (int i = 0; i < rules.size(); i++) {
+ int j = (rules.size() - i) - 1;
+ try {
+ Rule rule = rules.get(j);
+ if (debug) {
+ log.debug(" Fire end() for " + rule);
+ }
+ rule.end(namespaceURI, name);
+ } catch (Exception e) {
+ throw this.getDigester().createSAXException(e);
+ } catch (Error e) {
+ throw e;
+ }
+ }
+ }
+ }
+
+}
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginCreateRule.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginCreateRule.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginCreateRule.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginDeclarationRule.java
URL: http://svn.apache.org/viewvc/commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginDeclarationRule.java?rev=1072175&view=auto
==============================================================================
--- commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginDeclarationRule.java (added)
+++ commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginDeclarationRule.java Fri Feb 18 22:26:49 2011
@@ -0,0 +1,101 @@
+/* $Id$
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.digester3.plugins;
+
+import java.util.Properties;
+
+import org.apache.commons.digester3.Digester;
+import org.apache.commons.digester3.Rule;
+import org.xml.sax.Attributes;
+
+/**
+ * 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.
+ * <p>
+ * Normally, a PluginDeclarationRule is added to a Digester instance with
+ * the pattern "{root}/plugin" or "* /plugin" where {root} is the name of
+ * the root tag in the input document.
+ */
+public class PluginDeclarationRule extends Rule {
+
+ /**
+ * Invoked upon reading a tag defining a plugin declaration. The tag
+ * must have the following mandatory attributes:
+ * <ul>
+ * <li> id </li>
+ * <li> class </li>
+ * </ul>
+ *
+ *@param namespace The xml namespace in which the xml element which
+ * triggered this rule resides.
+ *@param name The name of the xml element which triggered this rule.
+ *@param attributes The set of attributes on the xml element which
+ * triggered this rule.
+ *@exception java.lang.Exception
+ */
+ @Override
+ public void begin(String namespace, String name, Attributes attributes) throws Exception {
+ int nAttrs = attributes.getLength();
+ Properties props = new Properties();
+ for(int i=0; i<nAttrs; ++i) {
+ String key = attributes.getLocalName(i);
+ if ((key == null) || (key.length() == 0)) {
+ key = attributes.getQName(i);
+ }
+ String value = attributes.getValue(i);
+ props.setProperty(key, value);
+ }
+
+ try {
+ declarePlugin(getDigester(), props);
+ } catch(PluginInvalidInputException ex) {
+ throw new PluginInvalidInputException(String.format("Error on element [%s]:",
+ getDigester().getMatch(),
+ ex.getMessage()), ex);
+ }
+ }
+
+ public static void declarePlugin(Digester digester, Properties props) throws PluginException {
+ String id = props.getProperty("id");
+ String pluginClassName = props.getProperty("class");
+
+ if (id == null) {
+ throw new PluginInvalidInputException("mandatory attribute id not present on plugin declaration");
+ }
+
+ if (pluginClassName == null) {
+ throw new PluginInvalidInputException("mandatory attribute class not present on plugin declaration");
+ }
+
+ Declaration newDecl = new Declaration(pluginClassName);
+ newDecl.setId(id);
+ newDecl.setProperties(props);
+
+ PluginRules rc = (PluginRules) digester.getRules();
+ PluginManager pm = rc.getPluginManager();
+
+ newDecl.init(digester, pm);
+ pm.addDeclaration(newDecl);
+
+ // Note that it is perfectly safe to redeclare a plugin, because
+ // the declaration doesn't add any rules to digester; all it does
+ // is create a RuleLoader instance whch is *capable* of adding the
+ // rules to the digester.
+ }
+
+}
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginDeclarationRule.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginDeclarationRule.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginDeclarationRule.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginInvalidInputException.java
URL: http://svn.apache.org/viewvc/commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginInvalidInputException.java?rev=1072175&view=auto
==============================================================================
--- commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginInvalidInputException.java (added)
+++ commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginInvalidInputException.java Fri Feb 18 22:26:49 2011
@@ -0,0 +1,49 @@
+/* $Id$
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.digester3.plugins;
+
+/**
+ * Thrown when an error occurs due to bad data in the file being parsed.
+ */
+public class PluginInvalidInputException extends PluginException {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * @param cause underlying exception that caused this to be thrown
+ */
+ public PluginInvalidInputException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * @param msg describes the reason this exception is being thrown.
+ */
+ public PluginInvalidInputException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * @param msg describes the reason this exception is being thrown.
+ * @param cause underlying exception that caused this to be thrown
+ */
+ public PluginInvalidInputException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+}
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginInvalidInputException.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginInvalidInputException.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginInvalidInputException.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginManager.java
URL: http://svn.apache.org/viewvc/commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginManager.java?rev=1072175&view=auto
==============================================================================
--- commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginManager.java (added)
+++ commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginManager.java Fri Feb 18 22:26:49 2011
@@ -0,0 +1,171 @@
+/* $Id$
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.digester3.plugins;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.commons.digester3.Digester;
+import org.apache.commons.logging.Log;
+
+/**
+ * Coordinates between PluginDeclarationRule and PluginCreateRule objects,
+ * providing a place to share data between instances of these rules.
+ * <p>
+ * One instance of this class exists per PluginRules instance.
+ */
+public class PluginManager {
+
+ /** Map of classname->Declaration */
+ private final Map<String, Declaration> declarationsByClass = new HashMap<String, Declaration>();
+
+ /** Map of id->Declaration */
+ private final Map<String, Declaration> declarationsById = new HashMap<String, Declaration>();
+
+ /** the parent manager to which this one may delegate lookups. */
+ private PluginManager parent;
+
+ /**
+ * The object containing data that should only exist once for each
+ * Digester instance.
+ */
+ private PluginContext pluginContext;
+
+ /** Construct a "root" PluginManager, ie one with no parent. */
+ public PluginManager(PluginContext r) {
+ pluginContext = r;
+ }
+
+ /**
+ * Construct a "child" PluginManager. When declarations are added to
+ * a "child", they are stored within the child and do not modify the
+ * parent, so when the child goes out of scope, those declarations
+ * disappear. When asking a "child" to retrieve a declaration, it
+ * delegates the search to its parent if it does not hold a matching
+ * entry itself.
+ * <p>
+ * @param parent must be non-null.
+ */
+ public PluginManager(PluginManager parent) {
+ this.parent = parent;
+ this.pluginContext = parent.pluginContext;
+ }
+
+ /**
+ * Add the declaration to the set of known declarations.
+ * <p>
+ * TODO: somehow get a reference to a Digester object
+ * so that we can really log here. Currently, all
+ * logging is disabled from this method.
+ *
+ *@param decl an object representing a plugin class.
+ */
+ public void addDeclaration(Declaration decl) {
+ Log log = LogUtils.getLogger(null);
+ boolean debug = log.isDebugEnabled();
+
+ Class<?> pluginClass = decl.getPluginClass();
+ String id = decl.getId();
+
+ declarationsByClass.put(pluginClass.getName(), decl);
+
+ if (id != null) {
+ declarationsById.put(id, decl);
+ if (debug) {
+ log.debug(
+ "Indexing plugin-id [" + id + "]" +
+ " -> class [" + pluginClass.getName() + "]");
+ }
+ }
+ }
+
+ /**
+ * Return the declaration object with the specified class.
+ * If no such plugin is known, null is returned.
+ */
+ public Declaration getDeclarationByClass(String className) {
+ Declaration decl =
+ declarationsByClass.get(className);
+
+ if ((decl == null) && (parent != null)) {
+ decl = parent.getDeclarationByClass(className);
+ }
+
+ return decl;
+ }
+
+ /**
+ * Return the declaration object with the specified id.
+ * If no such plugin is known, null is returned.
+ *
+ *@param id Description of the Parameter
+ *@return The declaration value
+ */
+ public Declaration getDeclarationById(String id) {
+ Declaration decl = declarationsById.get(id);
+
+ if ((decl == null) && (parent != null)) {
+ decl = parent.getDeclarationById(id);
+ }
+
+ return decl;
+ }
+
+ /**
+ * Given a plugin class and some associated properties, scan the
+ * list of known RuleFinder instances until one detects a source of
+ * custom rules for this plugin (aka a RuleLoader).
+ * <p>
+ * If no source of custom rules can be found, null is returned.
+ */
+ public RuleLoader findLoader(Digester digester, String id, Class<?> pluginClass, Properties props) throws PluginException {
+ // iterate over the list of RuleFinders, trying each one
+ // until one of them locates a source of dynamic rules given
+ // this specific plugin class and the associated declaration
+ // properties.
+ Log log = LogUtils.getLogger(digester);
+ boolean debug = log.isDebugEnabled();
+ log.debug("scanning ruleFinders to locate loader..");
+
+ List<RuleFinder> ruleFinders = pluginContext.getRuleFinders();
+ RuleLoader ruleLoader = null;
+ try {
+ for (Iterator<RuleFinder> i = ruleFinders.iterator(); i.hasNext() && ruleLoader == null;) {
+ RuleFinder finder = i.next();
+ if (debug) {
+ log.debug("checking finder of type " + finder.getClass().getName());
+ }
+ ruleLoader = finder.findLoader(digester, pluginClass, props);
+ }
+ }
+ catch(PluginException e) {
+ throw new PluginException(
+ "Unable to locate plugin rules for plugin"
+ + " with id [" + id + "]"
+ + ", and class [" + pluginClass.getName() + "]"
+ + ":" + e.getMessage(), e.getCause());
+ }
+ log.debug("scanned ruleFinders.");
+
+ return ruleLoader;
+ }
+
+}
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginManager.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/digester3/trunk/src/main/java/org/apache/commons/digester3/plugins/PluginManager.java
------------------------------------------------------------------------------
svn:mime-type = text/plain