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 static org.apache.commons.digester3.binder.DigesterLoader.newLoader;
023
024import java.io.ByteArrayInputStream;
025import java.io.ByteArrayOutputStream;
026import java.io.IOException;
027import java.io.InputStream;
028
029import org.apache.commons.digester3.Digester;
030import org.apache.commons.digester3.plugins.PluginException;
031import org.apache.commons.digester3.plugins.RuleLoader;
032import org.apache.commons.digester3.xmlrules.FromXmlRulesModule;
033import org.apache.commons.logging.Log;
034import org.xml.sax.InputSource;
035
036/**
037 * A rule-finding algorithm which loads an xmlplugins-format file.
038 * <p>
039 * Note that the "include" feature of xmlrules is not supported.
040 * 
041 * @since 1.6
042 */
043public class LoaderFromStream
044    extends RuleLoader
045{
046
047    private final byte[] input;
048
049    /**
050     * The contents of the input stream are loaded into memory, and cached for later use.
051     * <p>
052     * The caller is responsible for closing the input stream after this method has returned.
053     *
054     * @param s the input stream has to be loaded into memory
055     * @throws Exception if any error occurs while reading the input stream
056     */
057    public LoaderFromStream( InputStream s )
058        throws Exception
059    {
060        try
061        {
062            ByteArrayOutputStream baos = new ByteArrayOutputStream();
063            byte[] buf = new byte[256];
064            for ( ;; )
065            {
066                int i = s.read( buf );
067                if ( i == -1 )
068                {
069                    break;
070                }
071                baos.write( buf, 0, i );
072            }
073            input = baos.toByteArray();
074        }
075        finally
076        {
077            try
078            {
079                if ( s != null )
080                {
081                    s.close();
082                }
083            }
084            catch ( IOException e )
085            {
086                // close quietly
087            }
088        }
089    }
090
091    /**
092     * {@inheritDoc}
093     */
094    @Override
095    public void addRules( final Digester d, final String path )
096        throws PluginException
097    {
098        Log log = d.getLogger();
099        boolean debug = log.isDebugEnabled();
100        if ( debug )
101        {
102            log.debug( "LoaderFromStream: loading rules for plugin at path [" + path + "]" );
103        }
104
105        // Note that this input-source doesn't have any idea of its
106        // system id, so it has no way of resolving relative URLs
107        // such as the "include" feature of xmlrules. This is ok,
108        // because that doesn't work well with our approach of
109        // caching the input data in memory anyway.
110
111        final InputSource source = new InputSource( new ByteArrayInputStream( input ) );
112        newLoader( new FromXmlRulesModule()
113        {
114
115            @Override
116            protected void loadRules()
117            {
118                useRootPath( path );
119                loadXMLRules( source );
120            }
121
122        } ).createRuleSet().addRuleInstances( d );
123    }
124
125}