001    /* 
002        Licensed to the Apache Software Foundation (ASF) under one
003        or more contributor license agreements.  See the NOTICE file
004        distributed with this work for additional information
005        regarding copyright ownership.  The ASF licenses this file
006        to you under the Apache License, Version 2.0 (the
007        "License"); you may not use this file except in compliance
008        with 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,
013        software distributed under the License is distributed on an
014        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015        KIND, either express or implied.  See the License for the
016        specific language governing permissions and limitations
017        under the License.  
018     */
019    
020    package org.apache.wiki.util;
021    
022    import org.apache.commons.lang.StringUtils;
023    import org.apache.log4j.Logger;
024    import org.jdom2.Document;
025    import org.jdom2.Element;
026    import org.jdom2.JDOMException;
027    import org.jdom2.filter.Filters;
028    import org.jdom2.input.SAXBuilder;
029    import org.jdom2.xpath.XPathExpression;
030    import org.jdom2.xpath.XPathFactory;
031    
032    import java.io.IOException;
033    import java.io.InputStream;
034    import java.net.URL;
035    import java.util.ArrayList;
036    import java.util.Collections;
037    import java.util.Enumeration;
038    import java.util.HashSet;
039    import java.util.List;
040    import java.util.Set;
041    
042    /**
043     *  Utility class to parse XML files.
044     *  <p>
045     *  This uses JDOM2 as its backing implementation.
046     *  </p>
047     *  
048     * @since 2.10
049     */
050    public final class XmlUtil
051    {   
052        private static final Logger log = Logger.getLogger( XmlUtil.class );
053        
054        private XmlUtil() {}
055        
056        /**
057         * Parses the given XML file and returns the requested nodes. If there's an error accessing or parsing the file, an
058         * empty list is returned.
059         * 
060         * @param xml file to parse; matches all resources from classpath, filters repeated items.
061         * @param requestedNodes requestd nodes on the xml file
062         * @return the requested nodes of the XML file.
063         */
064        public static List<Element> parse( String xml, String requestedNodes )
065        {
066            if( StringUtils.isNotEmpty( xml ) && StringUtils.isNotEmpty( requestedNodes ) ) {
067                Set<Element> readed = new HashSet<Element>();
068                SAXBuilder builder = new SAXBuilder();
069                try {
070                    Enumeration< URL > resources = XmlUtil.class.getClassLoader().getResources( xml );
071                    while( resources.hasMoreElements() ) {
072                        URL resource = resources.nextElement();
073                        log.debug( "reading " + resource.toString() );
074                        Document doc = builder.build( resource );
075                        XPathFactory xpfac = XPathFactory.instance();
076                        XPathExpression<Element> xp = xpfac.compile( requestedNodes, Filters.element() );
077                        readed.addAll( xp.evaluate( doc ) ); // filter out repeated items
078                    }
079                    return new ArrayList<Element>( readed );
080                } catch ( IOException ioe ) {
081                    log.error( "Couldn't load all " + xml + " resources", ioe );
082                } catch ( JDOMException jdome ) {
083                    log.error( "error parsing " + xml + " resources", jdome );
084                }
085            }
086            return Collections.<Element>emptyList();
087        }
088        
089        
090        /**
091         * Parses the given stream and returns the requested nodes. If there's an error accessing or parsing the stream, an
092         * empty list is returned.
093         * 
094         * @param xmlStream stream to parse.
095         * @param requestedNodes requestd nodes on the xml stream.
096         * @return the requested nodes of the XML stream.
097         */
098        public static List<Element> parse( InputStream xmlStream, String requestedNodes )
099        {
100            if( xmlStream != null && StringUtils.isNotEmpty( requestedNodes ) ) {
101                SAXBuilder builder = new SAXBuilder();
102                try {
103                    Document doc = builder.build(xmlStream);
104                    XPathFactory xpfac = XPathFactory.instance();
105                    XPathExpression< Element > xp = xpfac.compile(requestedNodes,Filters.element());
106                    return xp.evaluate( doc );
107                } catch ( IOException ioe ) {
108                    log.error( "Couldn't load all " + xmlStream + " resources", ioe );
109                } catch ( JDOMException jdome ) {
110                    log.error( "error parsing " + xmlStream + " resources", jdome );
111                }
112            }       
113            return Collections.<Element>emptyList();
114        }
115    
116    }