| /* $Id: PluginManager.java,v 1.14 2004/05/10 06:44:13 skitching Exp $ |
| * |
| * Copyright 2003-2004 The Apache Software Foundation. |
| * |
| * Licensed 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.digester.plugins; |
| |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Properties; |
| import java.util.Iterator; |
| |
| import org.apache.commons.digester.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. |
| * |
| * @since 1.6 |
| */ |
| |
| public class PluginManager { |
| |
| /** Map of classname->Declaration */ |
| private HashMap declarationsByClass = new HashMap(); |
| |
| /** Map of id->Declaration */ |
| private HashMap declarationsById = new HashMap(); |
| |
| /** 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; |
| |
| //------------------- constructors --------------------------------------- |
| |
| /** 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; |
| } |
| |
| //------------------- methods -------------------------------------------- |
| |
| /** |
| * 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 = |
| (Declaration) 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 = (Declaration) 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 ruleFinders = pluginContext.getRuleFinders(); |
| RuleLoader ruleLoader = null; |
| try { |
| for(Iterator i = ruleFinders.iterator(); |
| i.hasNext() && ruleLoader == null; ) { |
| |
| RuleFinder finder = (RuleFinder) 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; |
| } |
| } |