001: /* $Id: PluginManager.java 471661 2006-11-06 08:09:25Z skitching $
002: *
003: * Licensed to the Apache Software Foundation (ASF) under one or more
004: * contributor license agreements. See the NOTICE file distributed with
005: * this work for additional information regarding copyright ownership.
006: * The ASF licenses this file to You under the Apache License, Version 2.0
007: * (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: package org.apache.commons.digester.plugins;
020:
021: import java.util.HashMap;
022: import java.util.List;
023: import java.util.Properties;
024: import java.util.Iterator;
025:
026: import org.apache.commons.digester.Digester;
027:
028: import org.apache.commons.logging.Log;
029:
030: /**
031: * Coordinates between PluginDeclarationRule and PluginCreateRule objects,
032: * providing a place to share data between instances of these rules.
033: * <p>
034: * One instance of this class exists per PluginRules instance.
035: *
036: * @since 1.6
037: */
038:
039: public class PluginManager {
040:
041: /** Map of classname->Declaration */
042: private HashMap declarationsByClass = new HashMap();
043:
044: /** Map of id->Declaration */
045: private HashMap declarationsById = new HashMap();
046:
047: /** the parent manager to which this one may delegate lookups. */
048: private PluginManager parent;
049:
050: /**
051: * The object containing data that should only exist once for each
052: * Digester instance.
053: */
054: private PluginContext pluginContext;
055:
056: //------------------- constructors ---------------------------------------
057:
058: /** Construct a "root" PluginManager, ie one with no parent. */
059: public PluginManager(PluginContext r) {
060: pluginContext = r;
061: }
062:
063: /**
064: * Construct a "child" PluginManager. When declarations are added to
065: * a "child", they are stored within the child and do not modify the
066: * parent, so when the child goes out of scope, those declarations
067: * disappear. When asking a "child" to retrieve a declaration, it
068: * delegates the search to its parent if it does not hold a matching
069: * entry itself.
070: * <p>
071: * @param parent must be non-null.
072: */
073: public PluginManager(PluginManager parent) {
074: this .parent = parent;
075: this .pluginContext = parent.pluginContext;
076: }
077:
078: //------------------- methods --------------------------------------------
079:
080: /**
081: * Add the declaration to the set of known declarations.
082: * <p>
083: * TODO: somehow get a reference to a Digester object
084: * so that we can really log here. Currently, all
085: * logging is disabled from this method.
086: *
087: *@param decl an object representing a plugin class.
088: */
089: public void addDeclaration(Declaration decl) {
090: Log log = LogUtils.getLogger(null);
091: boolean debug = log.isDebugEnabled();
092:
093: Class pluginClass = decl.getPluginClass();
094: String id = decl.getId();
095:
096: declarationsByClass.put(pluginClass.getName(), decl);
097:
098: if (id != null) {
099: declarationsById.put(id, decl);
100: if (debug) {
101: log.debug("Indexing plugin-id [" + id + "]"
102: + " -> class [" + pluginClass.getName() + "]");
103: }
104: }
105: }
106:
107: /**
108: * Return the declaration object with the specified class.
109: * If no such plugin is known, null is returned.
110: */
111: public Declaration getDeclarationByClass(String className) {
112: Declaration decl = (Declaration) declarationsByClass
113: .get(className);
114:
115: if ((decl == null) && (parent != null)) {
116: decl = parent.getDeclarationByClass(className);
117: }
118:
119: return decl;
120: }
121:
122: /**
123: * Return the declaration object with the specified id.
124: * If no such plugin is known, null is returned.
125: *
126: *@param id Description of the Parameter
127: *@return The declaration value
128: */
129: public Declaration getDeclarationById(String id) {
130: Declaration decl = (Declaration) declarationsById.get(id);
131:
132: if ((decl == null) && (parent != null)) {
133: decl = parent.getDeclarationById(id);
134: }
135:
136: return decl;
137: }
138:
139: /**
140: * Given a plugin class and some associated properties, scan the
141: * list of known RuleFinder instances until one detects a source of
142: * custom rules for this plugin (aka a RuleLoader).
143: * <p>
144: * If no source of custom rules can be found, null is returned.
145: */
146: public RuleLoader findLoader(Digester digester, String id,
147: Class pluginClass, Properties props) throws PluginException {
148:
149: // iterate over the list of RuleFinders, trying each one
150: // until one of them locates a source of dynamic rules given
151: // this specific plugin class and the associated declaration
152: // properties.
153: Log log = LogUtils.getLogger(digester);
154: boolean debug = log.isDebugEnabled();
155: log.debug("scanning ruleFinders to locate loader..");
156:
157: List ruleFinders = pluginContext.getRuleFinders();
158: RuleLoader ruleLoader = null;
159: try {
160: for (Iterator i = ruleFinders.iterator(); i.hasNext()
161: && ruleLoader == null;) {
162:
163: RuleFinder finder = (RuleFinder) i.next();
164: if (debug) {
165: log.debug("checking finder of type "
166: + finder.getClass().getName());
167: }
168: ruleLoader = finder.findLoader(digester, pluginClass,
169: props);
170: }
171: } catch (PluginException e) {
172: throw new PluginException(
173: "Unable to locate plugin rules for plugin"
174: + " with id [" + id + "]" + ", and class ["
175: + pluginClass.getName() + "]" + ":"
176: + e.getMessage(), e.getCause());
177: }
178: log.debug("scanned ruleFinders.");
179:
180: return ruleLoader;
181: }
182: }
|