001 /* $Id: PluginManager.java 729122 2008-12-23 21:14:13Z rahul $ 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<String, Declaration> declarationsByClass = new HashMap<String, Declaration>(); 043 044 /** Map of id->Declaration */ 045 private HashMap<String, Declaration> declarationsById = new HashMap<String, Declaration>(); 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( 102 "Indexing plugin-id [" + id + "]" + 103 " -> class [" + pluginClass.getName() + "]"); 104 } 105 } 106 } 107 108 /** 109 * Return the declaration object with the specified class. 110 * If no such plugin is known, null is returned. 111 */ 112 public Declaration getDeclarationByClass(String className) { 113 Declaration decl = 114 (Declaration) declarationsByClass.get(className); 115 116 if ((decl == null) && (parent != null)) { 117 decl = parent.getDeclarationByClass(className); 118 } 119 120 return decl; 121 } 122 123 /** 124 * Return the declaration object with the specified id. 125 * If no such plugin is known, null is returned. 126 * 127 *@param id Description of the Parameter 128 *@return The declaration value 129 */ 130 public Declaration getDeclarationById(String id) { 131 Declaration decl = (Declaration) declarationsById.get(id); 132 133 if ((decl == null) && (parent != null)) { 134 decl = parent.getDeclarationById(id); 135 } 136 137 return decl; 138 } 139 140 /** 141 * Given a plugin class and some associated properties, scan the 142 * list of known RuleFinder instances until one detects a source of 143 * custom rules for this plugin (aka a RuleLoader). 144 * <p> 145 * If no source of custom rules can be found, null is returned. 146 */ 147 public RuleLoader findLoader(Digester digester, String id, 148 Class<?> pluginClass, Properties props) 149 throws PluginException { 150 151 // iterate over the list of RuleFinders, trying each one 152 // until one of them locates a source of dynamic rules given 153 // this specific plugin class and the associated declaration 154 // properties. 155 Log log = LogUtils.getLogger(digester); 156 boolean debug = log.isDebugEnabled(); 157 log.debug("scanning ruleFinders to locate loader.."); 158 159 List<RuleFinder> ruleFinders = pluginContext.getRuleFinders(); 160 RuleLoader ruleLoader = null; 161 try { 162 for(Iterator<RuleFinder> i = ruleFinders.iterator(); 163 i.hasNext() && ruleLoader == null; ) { 164 165 RuleFinder finder = (RuleFinder) i.next(); 166 if (debug) { 167 log.debug("checking finder of type " + finder.getClass().getName()); 168 } 169 ruleLoader = finder.findLoader(digester, pluginClass, props); 170 } 171 } 172 catch(PluginException e) { 173 throw new PluginException( 174 "Unable to locate plugin rules for plugin" 175 + " with id [" + id + "]" 176 + ", and class [" + pluginClass.getName() + "]" 177 + ":" + e.getMessage(), e.getCause()); 178 } 179 log.debug("scanned ruleFinders."); 180 181 return ruleLoader; 182 } 183 }