    001    /* $Id: FinderFromResource.java 729125 2008-12-23 21:21:07Z 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.strategies;
    020
    021    import java.util.Properties;
    022    import java.io.InputStream;
    023
    024    import org.apache.commons.digester.Digester;
    025    import org.apache.commons.digester.plugins.RuleFinder;
    026    import org.apache.commons.digester.plugins.RuleLoader;
    027    import org.apache.commons.digester.plugins.PluginException;
    028
    029    /**
    030     * A rule-finding algorithm which expects the user to specify a resource
    031     * name (ie a file in the classpath). The file is expected to contain Digester
    032     * rules in xmlrules format.
    033     *
    034     * @since 1.6
    035     */
    036
    037    public class FinderFromResource extends RuleFinder {
    038        /**
    039         * Name of xml attribute on the plugin declaration which is used
    040         * to configure rule-loading for that declaration.
    041         */
    042        public static String DFLT_RESOURCE_ATTR = "resource";
    043
    044        /** See {@link #findLoader}. */
    045        private String resourceAttr;
    046
    047        /** Constructor. */
    048        public FinderFromResource() {
    049            this(DFLT_RESOURCE_ATTR);
    050        }
    051
    052        /** See {@link #findLoader}. */
    053        public FinderFromResource(String resourceAttr) {
    054            this.resourceAttr = resourceAttr;
    055        }
    056
    057        /**
    058         * If there exists a property with the name matching constructor param
    059         * resourceAttr, then load that file, run it through the xmlrules
    060         * module and return an object encapsulating those rules.
    061         * <p>
    062         * If there is no matching property provided, then just return null.
    063         * <p>
    064         * The returned object (when non-null) will add the selected rules to
    065         * the digester whenever its addRules method is invoked.
    066         */
    067        public RuleLoader findLoader(Digester d, Class<?> pluginClass, Properties p)
    068                            throws PluginException {
    069
    070            String resourceName = p.getProperty(resourceAttr);
    071            if (resourceName == null) {
    072                // nope, user hasn't requested dynamic rules to be loaded
    073                // from a specific file.
    074                return null;
    075            }
    076
    077            InputStream is =
    078                pluginClass.getClassLoader().getResourceAsStream(
    079                    resourceName);
    080
    081            if (is == null) {
    082                throw new PluginException(
    083                    "Resource " + resourceName + " not found.");
    084            }
    085
    086             return loadRules(d, pluginClass, is, resourceName);
    087        }
    088
    089        /**
    090         * Open the specified resource file (ie a file in the classpath,
    091         * including being within a jar in the classpath), run it through
    092         * the xmlrules module and return an object encapsulating those rules.
    093         *
    094         * @param d is the digester into which rules will eventually be loaded.
    095         * @param pluginClass is the class whose xml params the rules are parsing.
    096         * @param is is where the xmlrules will be read from, and must be non-null.
    097         * @param resourceName is a string describing the source of the xmlrules,
    098         *  for use in generating error messages.
    099         */
    100        public static RuleLoader loadRules(Digester d, Class<?> pluginClass,
    101                            InputStream is, String resourceName)
    102                            throws PluginException {
    103
    104            try {
    105                RuleLoader loader = new LoaderFromStream(is);
    106                return loader;
    107            } catch(Exception e) {
    108                throw new PluginException(
    109                    "Unable to load xmlrules from resource [" +
    110                    resourceName + "]", e);
    111            } finally {
    112                try {
    113                    is.close();
    114                } catch(java.io.IOException ioe) {
    115                    throw new PluginException(
    116                        "Unable to close stream for resource [" +
    117                        resourceName + "]", ioe);
    118                }
    119            }
    120        }
    121    }
    122