001package org.apache.commons.digester3.plugins.strategies;
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.io.FileInputStream;
023import java.io.IOException;
024import java.io.InputStream;
025import java.util.Properties;
026
027import org.apache.commons.digester3.Digester;
028import org.apache.commons.digester3.plugins.PluginException;
029import org.apache.commons.digester3.plugins.RuleFinder;
030import org.apache.commons.digester3.plugins.RuleLoader;
031
032/**
033 * A rule-finding algorithm which expects the user to specify an absolute or relative path in the plugin declaration.
034 * <p>
035 * The file is expected to contain Digester rules in xmlrules format.
036 * 
037 * @since 1.6
038 */
039public class FinderFromFile
040    extends RuleFinder
041{
042
043    /**
044     * The default XML attribute that needs to be present on a plugin declaration in order to specify the file to
045     * load rules from.
046     */
047    private static final String DFLT_FILENAME_ATTR = "file";
048
049    /** See {@link #findLoader}. */
050    private final String filenameAttr;
051
052    /** See {@link #findLoader}. */
053    public FinderFromFile()
054    {
055        this( DFLT_FILENAME_ATTR );
056    }
057
058    /**
059     * See {@link #findLoader}.
060     *
061     * @param filenameAttr the XML attribute that needs to be present on a plugin declaration in order to specify the
062     *        file to load rules from.
063     */
064    public FinderFromFile( String filenameAttr )
065    {
066        this.filenameAttr = filenameAttr;
067    }
068
069    /**
070     * If there exists a property with the name specified in the constructor, then load that file, run it through the
071     * xmlrules module and return an object encapsulating those rules.
072     * <p>
073     * If there is no matching property provided, then just return null.
074     * <p>
075     * The returned object (when non-null) will add the selected rules to the digester whenever its addRules method is
076     * invoked.
077     *
078     * @param d The digester instance where locating plugin classes
079     * @param pluginClass The plugin Java class
080     * @param p The properties object that holds any xml attributes the user may have specified on the plugin
081     *          declaration in order to indicate how to locate the plugin rules.
082     * @return a source of digester rules for the specified plugin class.
083     * @throws PluginException if the algorithm finds a source of rules, but there is something invalid
084     *         about that source.
085     */
086    @Override
087    public RuleLoader findLoader( Digester d, Class<?> pluginClass, Properties p )
088        throws PluginException
089    {
090
091        String rulesFileName = p.getProperty( filenameAttr );
092        if ( rulesFileName == null )
093        {
094            // nope, user hasn't requested dynamic rules to be loaded
095            // from a specific file.
096            return null;
097        }
098
099        InputStream is = null;
100        try
101        {
102            is = new FileInputStream( rulesFileName );
103        }
104        catch ( IOException ioe )
105        {
106            throw new PluginException( "Unable to process file [" + rulesFileName + "]", ioe );
107        }
108
109        try
110        {
111            RuleLoader loader = new LoaderFromStream( is );
112            return loader;
113        }
114        catch ( Exception e )
115        {
116            throw new PluginException( "Unable to load xmlrules from file [" + rulesFileName + "]", e );
117        }
118        finally
119        {
120            try
121            {
122                is.close();
123            }
124            catch ( IOException ioe )
125            {
126                throw new PluginException( "Unable to close stream for file [" + rulesFileName + "]", ioe );
127            }
128        }
129    }
130
131}