001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.pipeline.config;
019    
020    import java.io.File;
021    import java.io.IOException;
022    import java.io.InputStream;
023    import java.net.URL;
024    import java.util.ArrayList;
025    import java.util.Iterator;
026    import java.util.List;
027    import org.apache.commons.digester.Digester;
028    import org.apache.commons.digester.RuleSet;
029    import org.apache.commons.pipeline.PipelineCreationException;
030    import org.apache.commons.pipeline.Pipeline;
031    import org.xml.sax.SAXException;
032    
033    
034    /**
035     * This factory is designed to simplify creating a pipeline using Digester.
036     * @see  PipelineRuleSet for additional information on the format of the
037     * XML configuration file.
038     */
039    public class DigesterPipelineFactory implements org.apache.commons.pipeline.PipelineFactory {
040        
041        /** Digester rule sets used to configure the Digester instance. */
042        private List<RuleSet> ruleSets = new ArrayList<RuleSet>();
043        
044        /**
045         * Factory will create a pipeline from the specified Digester configuration file
046         * if this filename is not null.
047         */
048        private URL confURL;
049        
050        /**
051         * A factory created by this constructor will create a pipeline from the specified
052         * XML configuration file.
053         * @param configFile the XML file containing pipeline configuration information
054         */
055        public DigesterPipelineFactory(URL confURL) {
056            if (confURL == null) throw new IllegalArgumentException("Configuration file URL may not be null.");
057            this.confURL = confURL;
058        
059            //PipelineRuleSet needs a reference to {@link org.apache.commons.digester.RuleSet RuleSet}s
060            //used to parse the configuration file in case configuration is split up between multiple
061            //files.
062            ruleSets.add(new PipelineRuleSet(ruleSets));        
063        }
064        
065        /**
066         * Creates a new pipeline based upon the configuration of this factory instance.
067         * @throws org.apache.commons.pipeline.PipelineCreationException Thrown if an error is encountered parsing the configuration file.
068         * @return The newly created pipeline instance
069         */
070        public Pipeline createPipeline() throws PipelineCreationException {
071            try {
072                    Digester digester = new Digester();
073                    this.initDigester(digester);
074                    
075                InputStream in = confURL.openStream();
076                try {
077                    return (Pipeline) digester.parse(in);
078                } finally {
079                    in.close();
080                }
081            } catch (IOException e) {
082                throw new PipelineCreationException("An IOException occurred reading the configuration file: " + e.getMessage(), e);
083            } catch (SAXException e) {
084                throw new PipelineCreationException("A formatting error exists in the configuration file: " + e.getMessage(), e);
085            }
086        }
087        
088        /**
089         * Initialize a Digester instance with the rule sets provided to this factory.
090         * @param digester The digester instance to be initialized
091         */
092        public void initDigester(Digester digester) {
093            for (Iterator iter = ruleSets.iterator(); iter.hasNext();) {
094                digester.addRuleSet((RuleSet) iter.next());
095            }
096        }
097        
098        /**
099         * Adds a RuleSet to the list of rules available to Digester for parsing
100         * the configuration file.
101         * @param ruleSet The rule set to be added to the Digester
102         */
103        public void addRuleSet(RuleSet ruleSet) {
104            this.ruleSets.add(ruleSet);
105        }
106        
107        /**
108         * The simplest possible main method that creates a pipeline from a configuration file,
109         * then runs the pipeline processing from start to finish.
110         *
111         * When run from the command line, the only argument to this method should be
112         * the path to the configuration file.
113         *
114         * @param argv the command line arguments
115         */
116        public static void main(String[] argv) {
117            try {
118                File configFile = new File(argv[0]);
119                
120                DigesterPipelineFactory factory = new DigesterPipelineFactory(configFile.toURL());
121                Pipeline pipeline = factory.createPipeline();
122                for (int i = 1; i < argv.length; i++) {
123                    pipeline.getSourceFeeder().feed(argv[i]);
124                }
125                
126                System.out.println("Pipeline created, about to begin processing...");
127                
128                pipeline.start();
129                pipeline.finish();
130                
131                System.out.println("Pipeline successfully finished processing. See logs for details.");
132            } catch (Exception e) {
133                e.printStackTrace(System.err);
134            }
135        }
136    }