All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.lightbody.bmp.proxy.jetty.xml.XmlParser Maven / Gradle / Ivy

// ========================================================================
// $Id: XmlParser.java,v 1.21 2005/10/25 07:53:22 gregwilkins Exp $
// Copyright 1999-2004 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at 
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================
package net.lightbody.bmp.proxy.jetty.xml;

import net.lightbody.bmp.proxy.jetty.log.LogFactory;
import net.lightbody.bmp.proxy.jetty.util.LazyList;
import net.lightbody.bmp.proxy.jetty.util.LogSupport;
import org.apache.commons.logging.Log;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;

/*--------------------------------------------------------------*/
/**
 * XML Parser wrapper. This class wraps any standard JAXP1.1 parser with convieniant error and
 * entity handlers and a mini dom-like document tree.
 * 

* By default, the parser is created as a validating parser. This can be changed by setting the * "org.mortbay.xml.XmlParser.NotValidating" system property to true. * * @version $Id: XmlParser.java,v 1.21 2005/10/25 07:53:22 gregwilkins Exp $ * @author Greg Wilkins (gregw) */ public class XmlParser { private static Log log=LogFactory.getLog(XmlParser.class); private Map _redirectMap=new HashMap(); private SAXParser _parser; private String _xpath; private Object _xpaths; /* ------------------------------------------------------------ */ /** * Construct */ public XmlParser() { try { SAXParserFactory factory=SAXParserFactory.newInstance(); boolean notValidating=Boolean.getBoolean("XmlParser.NotValidating"); factory.setValidating(!notValidating); _parser=factory.newSAXParser(); try { if(!notValidating) _parser.getXMLReader().setFeature("http://apache.org/xml/features/validation/schema",true); } catch(Exception e) { log.warn("Schema validation may not be supported"); log.debug("",e); notValidating=true; } _parser.getXMLReader().setFeature("http://xml.org/sax/features/validation",!notValidating); _parser.getXMLReader().setFeature("http://xml.org/sax/features/namespaces",!notValidating); _parser.getXMLReader().setFeature("http://xml.org/sax/features/namespace-prefixes",!notValidating); } catch(Exception e) { log.warn(LogSupport.EXCEPTION,e); throw new Error(e.toString()); } } /* ------------------------------------------------------------ */ /** * Constructor. */ public XmlParser(boolean validating) { try { SAXParserFactory factory=SAXParserFactory.newInstance(); factory.setValidating(validating); _parser=factory.newSAXParser(); try { if(validating) _parser.getXMLReader().setFeature("http://apache.org/xml/features/validation/schema",validating); } catch(Exception e) { if(validating) log.warn("Schema validation may not be supported: ",e); else LogSupport.ignore(log,e); } _parser.getXMLReader().setFeature("http://xml.org/sax/features/validation",validating); _parser.getXMLReader().setFeature("http://xml.org/sax/features/namespaces",validating); _parser.getXMLReader().setFeature("http://xml.org/sax/features/namespace-prefixes",validating); } catch(Exception e) { log.warn(LogSupport.EXCEPTION,e); throw new Error(e.toString()); } } /* ------------------------------------------------------------ */ /** * @param name * @param entity */ public synchronized void redirectEntity(String name,URL entity) { if(entity!=null) _redirectMap.put(name,entity); } /* ------------------------------------------------------------ */ /** * * @return Returns the xpath. */ public String getXpath() { return _xpath; } /* ------------------------------------------------------------ */ /** Set an XPath * A very simple subset of xpath is supported to select a partial * tree. Currently only path like "/node1/nodeA | /node1/nodeB" * are supported. * @param xpath The xpath to set. */ public void setXpath(String xpath) { _xpath = xpath; StringTokenizer tok = new StringTokenizer(xpath,"| "); while(tok.hasMoreTokens()) _xpaths=LazyList.add(_xpaths, tok.nextToken()); } /* ------------------------------------------------------------ */ public synchronized Node parse(InputSource source) throws IOException,SAXException { Handler handler=new Handler(); XMLReader reader=_parser.getXMLReader(); reader.setContentHandler(handler); reader.setErrorHandler(handler); reader.setEntityResolver(handler); if(log.isDebugEnabled()) log.debug("parsing: sid="+source.getSystemId()+",pid="+source.getPublicId()); _parser.parse(source,handler); if(handler._error!=null) throw handler._error; Node doc=(Node)handler._top.get(0); handler.clear(); return doc; } /* ------------------------------------------------------------ */ /** * Parse string URL. */ public synchronized Node parse(String url) throws IOException,SAXException { if(log.isDebugEnabled()) log.debug("parse: "+url); return parse(new InputSource(url)); } /* ------------------------------------------------------------ */ /** * Parse File. */ public synchronized Node parse(File file) throws IOException,SAXException { if(log.isDebugEnabled()) log.debug("parse: "+file); return parse(new InputSource(file.toURL().toString())); } /* ------------------------------------------------------------ */ /** * Parse InputStream. */ public synchronized Node parse(InputStream in) throws IOException,SAXException { Handler handler=new Handler(); XMLReader reader=_parser.getXMLReader(); reader.setContentHandler(handler); reader.setErrorHandler(handler); reader.setEntityResolver(handler); _parser.parse(new InputSource(in),handler); if(handler._error!=null) throw handler._error; Node doc=(Node)handler._top.get(0); handler.clear(); return doc; } /* ------------------------------------------------------------ */ /** * Parse URL. */ public synchronized Node parse(URL url) throws IOException,SAXException { Node n=null; InputStream is=url.openStream(); try { n=parse(is); } finally { try { is.close(); } catch(Exception e) { // xerces closes streams you give it to parse, so this close() will throw an // exception. // This behavior is stupid, so we should not assume it. } } return n; } /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ private class NoopHandler extends DefaultHandler { Handler _next; int _depth; NoopHandler(Handler next) { this._next=next; } /* ------------------------------------------------------------ */ public void startElement(String uri,String localName,String qName,Attributes attrs) throws SAXException { _depth++; } /* ------------------------------------------------------------ */ public void endElement(String uri,String localName,String qName) throws SAXException { if (_depth==0) _parser.getXMLReader().setContentHandler(_next); else _depth--; } } /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ private class Handler extends DefaultHandler { Node _top=new Node(null,null,null); SAXParseException _error; private Node _context=_top; private NoopHandler _noop; Handler() { _noop = new NoopHandler(this); } /* ------------------------------------------------------------ */ void clear() { _top=null; _error=null; _context=null; } /* ------------------------------------------------------------ */ public void startElement(String uri,String localName,String qName,Attributes attrs) throws SAXException { String name=(uri==null||uri.equals(""))?qName:localName; Node node=new Node(_context,name,attrs); // check if the node matches any xpaths set? if (_xpaths!=null) { String path=node.getPath(); boolean match=false; for (int i=LazyList.size(_xpaths);!match&&i-->0;) { String xpath=(String)LazyList.get(_xpaths,i); match=path.equals(xpath) || xpath.startsWith(path) && xpath.length()>path.length() && xpath.charAt(path.length())=='/'; } if (match) { _context.add(node); _context=node; } else { _parser.getXMLReader().setContentHandler(_noop); } } else { _context.add(node); _context=node; } } /* ------------------------------------------------------------ */ public void endElement(String uri,String localName,String qName) throws SAXException { _context=_context._parent; } /* ------------------------------------------------------------ */ public void ignorableWhitespace(char buf[],int offset,int len) throws SAXException { } /* ------------------------------------------------------------ */ public void characters(char buf[],int offset,int len) throws SAXException { _context.add(new String(buf,offset,len)); } /* ------------------------------------------------------------ */ public void warning(SAXParseException ex) { log.debug(LogSupport.EXCEPTION,ex); log.warn("WARNING@"+getLocationString(ex)+" : "+ex.toString()); } /* ------------------------------------------------------------ */ public void error(SAXParseException ex) throws SAXException { // Save error and continue to report other errors if(_error==null) _error=ex; log.debug(LogSupport.EXCEPTION,ex); log.warn("ERROR@"+getLocationString(ex)+" : "+ex.toString()); } /* ------------------------------------------------------------ */ public void fatalError(SAXParseException ex) throws SAXException { _error=ex; log.debug(LogSupport.EXCEPTION,ex); log.warn("FATAL@"+getLocationString(ex)+" : "+ex.toString()); throw ex; } /* ------------------------------------------------------------ */ private String getLocationString(SAXParseException ex) { return ex.getSystemId()+" line:"+ex.getLineNumber()+" col:"+ex.getColumnNumber(); } /* ------------------------------------------------------------ */ public InputSource resolveEntity(String pid,String sid) { if(log.isDebugEnabled()) log.debug("resolveEntity("+pid+", "+sid+")"); URL entity=null; if(pid!=null) entity=(URL)_redirectMap.get(pid); if(entity==null) entity=(URL)_redirectMap.get(sid); if(entity==null) { String dtd=sid; if(dtd.lastIndexOf('/')>=0) dtd=dtd.substring(dtd.lastIndexOf('/')+1); if(log.isDebugEnabled()) log.debug("Can't exact match entity in redirect map, trying "+dtd); entity=(URL)_redirectMap.get(dtd); } if(entity!=null) { try { InputStream in=entity.openStream(); if(log.isDebugEnabled()) log.debug("Redirected entity "+sid+" --> "+entity); InputSource is=new InputSource(in); is.setSystemId(sid); return is; } catch(IOException e) { LogSupport.ignore(log,e); } } return null; } } /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ /** * XML Attribute. */ public static class Attribute { private String _name; private String _value; Attribute(String n,String v) { _name=n; _value=v; } public String getName() { return _name; } public String getValue() { return _value; } } /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ /** * XML Node. Represents an XML element with optional attributes and ordered content. */ public static class Node extends AbstractList { Node _parent; private ArrayList _list; private String _tag; private Attribute[] _attrs; private boolean _lastString=false; private String _path; /* ------------------------------------------------------------ */ Node(Node parent,String tag,Attributes attrs) { _parent=parent; _tag=tag; if(attrs!=null) { _attrs=new Attribute[attrs.getLength()]; for(int i=0;i"); for(int i=0;i<_list.size();i++) { Object o=_list.get(i); if(o==null) continue; if(o instanceof Node) ((Node)o).toString(buf,tag); else buf.append(o.toString()); } if(tag) { buf.append(""); } } else if(tag) buf.append("/>"); } /* ------------------------------------------------------------ */ /** * Iterator over named child nodes. * * @param tag The tag of the nodes. * @return Iterator over all child nodes with the specified tag. */ public Iterator iterator(final String tag) { return new Iterator() { int c=0; Node _node; /* -------------------------------------------------- */ public boolean hasNext() { if(_node!=null) return true; while(_list!=null&&c<_list.size()) { Object o=_list.get(c); if(o instanceof Node) { Node n=(Node)o; if(tag.equals(n._tag)) { _node=n; return true; } } c++; } return false; } /* -------------------------------------------------- */ public Object next() { try { if(hasNext()) return _node; throw new NoSuchElementException(); } finally { _node=null; c++; } } /* -------------------------------------------------- */ public void remove() { throw new UnsupportedOperationException("Not supported"); } }; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy