001package org.apache.commons.digester3.plugins;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.util.List;
023import java.util.LinkedList;
024
025import org.apache.commons.digester3.plugins.strategies.FinderFromClass;
026import org.apache.commons.digester3.plugins.strategies.FinderFromDfltClass;
027import org.apache.commons.digester3.plugins.strategies.FinderFromDfltMethod;
028import org.apache.commons.digester3.plugins.strategies.FinderFromDfltResource;
029import org.apache.commons.digester3.plugins.strategies.FinderFromFile;
030import org.apache.commons.digester3.plugins.strategies.FinderFromMethod;
031import org.apache.commons.digester3.plugins.strategies.FinderFromResource;
032import org.apache.commons.digester3.plugins.strategies.FinderSetProperties;
033
034/**
035 * Provides data and services which should exist only once per digester.
036 * <p>
037 * This class holds a number of useful items which should be shared by all plugin objects. Such data cannot be stored on
038 * the PluginRules or PluginManager classes, as there can be multiple instances of these at various times during a
039 * parse.
040 * <p>
041 * The name "Context" refers to the similarity between this class and a ServletContext class in a servlet engine. A
042 * ServletContext object provides access to the container's services such as obtaining global configuration parameters
043 * for the container, or getting access to logging services. For plugins, a Digester instance can be regarded as
044 * "the container".
045 * 
046 * @since 1.6
047 */
048public class PluginContext
049{
050
051    private static final String DFLT_PLUGIN_CLASS_ATTR_NS = null;
052
053    private static final String DFLT_PLUGIN_CLASS_ATTR = "plugin-class";
054
055    // the xml attribute the user uses on an xml element to specify
056    // the plugin's class
057    private static final String DFLT_PLUGIN_ID_ATTR_NS = null;
058
059    private static final String DFLT_PLUGIN_ID_ATTR = "plugin-id";
060
061    /** See {@link #setPluginClassAttribute}. */
062    private String pluginClassAttrNs = DFLT_PLUGIN_CLASS_ATTR_NS;
063
064    /** See {@link #setPluginClassAttribute}. */
065    private String pluginClassAttr = DFLT_PLUGIN_CLASS_ATTR;
066
067    /** See {@link #setPluginClassAttribute}. */
068    private String pluginIdAttrNs = DFLT_PLUGIN_ID_ATTR_NS;
069
070    /** See {@link #setPluginClassAttribute}. */
071    private String pluginIdAttr = DFLT_PLUGIN_ID_ATTR;
072
073    /**
074     * A list of RuleFinder objects used by all Declarations (and thus indirectly by all PluginCreateRules to locate the
075     * custom rules for plugin classes.
076     */
077    private List<RuleFinder> ruleFinders;
078
079    // ------------------- methods ---------------------------------------
080
081    /**
082     * Return the list of RuleFinder objects. Under normal circumstances this method creates a default list of these
083     * objects when first called (ie "on-demand" or "lazy initialization"). However if setRuleFinders has been called
084     * first, then the list specified there is returned.
085     * <p>
086     * It is explicitly permitted for the caller to modify this list by inserting or removing RuleFinder objects.
087     *
088     * @return the list of RuleFinder objects
089     */
090    public List<RuleFinder> getRuleFinders()
091    {
092        if ( ruleFinders == null )
093        {
094            // when processing a plugin declaration, attempts are made to
095            // find custom rules in the order in which the Finder objects
096            // are added below. However this list can be modified
097            ruleFinders = new LinkedList<RuleFinder>();
098            ruleFinders.add( new FinderFromFile() );
099            ruleFinders.add( new FinderFromResource() );
100            ruleFinders.add( new FinderFromClass() );
101            ruleFinders.add( new FinderFromMethod() );
102            ruleFinders.add( new FinderFromDfltMethod() );
103            ruleFinders.add( new FinderFromDfltClass() );
104            ruleFinders.add( new FinderFromDfltResource() );
105            ruleFinders.add( new FinderFromDfltResource( ".xml" ) );
106            ruleFinders.add( new FinderSetProperties() );
107        }
108        return ruleFinders;
109    }
110
111    /**
112     * Set the list of RuleFinder objects. This may be useful if working in a non-english language, allowing the
113     * application developer to replace the standard list with a list of objects which look for xml attributes in the
114     * local language.
115     * <p>
116     * If the intent is just to add an additional rule-finding algorithm, then it may be better to call #getRuleFinders,
117     * and insert a new object into the start of the list.
118     *
119     * @param ruleFinders the list of RuleFinder objects
120     */
121    public void setRuleFinders( List<RuleFinder> ruleFinders )
122    {
123        this.ruleFinders = ruleFinders;
124    }
125
126    /**
127     * Sets the xml attribute which the input xml uses to indicate to a PluginCreateRule which class should be
128     * instantiated.
129     * <p>
130     * Example:
131     * 
132     * <pre>
133     * setPluginClassAttribute( null, &quot;class&quot; );
134     * </pre>
135     * 
136     * will allow this in the input xml:
137     * 
138     * <pre>
139     *  &lt;root&gt;
140     *    &lt;some-plugin class="com.acme.widget"&gt; ......
141     * </pre>
142     * 
143     * instead of the default syntax:
144     * 
145     * <pre>
146     *  &lt;root&gt;
147     *    &lt;some-plugin plugin-class="com.acme.widget"&gt; ......
148     * </pre>
149     * 
150     * This is particularly useful if the input xml document is not in English.
151     * <p>
152     * Note that the xml attributes used by PluginDeclarationRules are not affected by this method.
153     * 
154     * @param namespaceUri is the namespace uri that the specified attribute is in. If the attribute is in no namespace,
155     *            then this should be null. Note that if a namespace is used, the attrName value should <i>not</i>
156     *            contain any kind of namespace-prefix. Note also that if you are using a non-namespace-aware parser,
157     *            this parameter <i>must</i> be null.
158     * @param attrName is the attribute whose value contains the name of the class to be instantiated.
159     */
160    public void setPluginClassAttribute( String namespaceUri, String attrName )
161    {
162        pluginClassAttrNs = namespaceUri;
163        pluginClassAttr = attrName;
164    }
165
166    /**
167     * Sets the xml attribute which the input xml uses to indicate to a PluginCreateRule which plugin declaration is
168     * being referenced.
169     * <p>
170     * Example:
171     * 
172     * <pre>
173     * setPluginIdAttribute( null, &quot;id&quot; );
174     * </pre>
175     * 
176     * will allow this in the input xml:
177     * 
178     * <pre>
179     *  &lt;root&gt;
180     *    &lt;some-plugin id="widget"&gt; ......
181     * </pre>
182     * 
183     * rather than the default behaviour:
184     * 
185     * <pre>
186     *  &lt;root&gt;
187     *    &lt;some-plugin plugin-id="widget"&gt; ......
188     * </pre>
189     * 
190     * This is particularly useful if the input xml document is not in English.
191     * <p>
192     * Note that the xml attributes used by PluginDeclarationRules are not affected by this method.
193     * 
194     * @param namespaceUri is the namespace uri that the specified attribute is in. If the attribute is in no namespace,
195     *            then this should be null. Note that if a namespace is used, the attrName value should <i>not</i>
196     *            contain any kind of namespace-prefix. Note also that if you are using a non-namespace-aware parser,
197     *            this parameter <i>must</i> be null.
198     * @param attrName is the attribute whose value contains the id of the plugin declaration to be used when
199     *            instantiating an object.
200     */
201    public void setPluginIdAttribute( String namespaceUri, String attrName )
202    {
203        pluginIdAttrNs = namespaceUri;
204        pluginIdAttr = attrName;
205    }
206
207    /**
208     * Get the namespace for the xml attribute which indicates to a PluginCreateRule which class is to be plugged in.
209     * <p>
210     * May be null (in fact, normally will be).
211     *
212     * @return the namespace for the xml attribute which indicates which class is to be plugged in.
213     */
214    public String getPluginClassAttrNs()
215    {
216        return pluginClassAttrNs;
217    }
218
219    /**
220     * Get the namespace for the xml attribute which indicates to a PluginCreateRule which class is to be plugged in.
221     * <p>
222     * The return value is never null.
223     *
224     * @return the namespace for the xml attribute which indicates which class is to be plugged in.
225     */
226    public String getPluginClassAttr()
227    {
228        return pluginClassAttr;
229    }
230
231    /**
232     * Get the namespace for the xml attribute which indicates to a PluginCreateRule which previous plugin declaration
233     * should be used.
234     * <p>
235     * May be null (in fact, normally will be).
236     *
237     * @return the namespace for the xml attribute which indicates which previous plugin declaration should be used.
238     */
239    public String getPluginIdAttrNs()
240    {
241        return pluginIdAttrNs;
242    }
243
244    /**
245     * Get the namespace for the xml attribute which indicates to a PluginCreateRule which previous plugin declaration
246     * should be used.
247     * <p>
248     * The return value is never null.
249     *
250     * @return the namespace for the xml attribute which indicates which previous plugin declaration should be used.
251     */
252    public String getPluginIdAttr()
253    {
254        return pluginIdAttr;
255    }
256
257}