Sunday, 31 July 2011

Create Xml Reader

   
/** 
 
 * The ObjectStyle Group Software License, version 1.1
 * ObjectStyle Group - http://objectstyle.org/
 
 * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
 * of the software. All rights reserved.
 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 
 * 3. The end-user documentation included with the redistribution, if any,
 *    must include the following acknowlegement:
 *    "This product includes software developed by independent contributors
 *    and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 
 * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
 *    or promote products derived from this software without prior written
 *    permission. For written permission, email
 *    "andrus at objectstyle dot org".
 
 * 5. Products derived from this software may not be called "ObjectStyle"
 *    or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
 *    names without prior written permission.
 
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 
 
 * This software consists of voluntary contributions made by many
 * individuals and hosted on ObjectStyle Group web site.  For more
 * information on the ObjectStyle Group, please see
 * <http://objectstyle.org/>.
 */

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.lang.reflect.Member;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;


import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

/**
 * Contains various unorganized static utility methods used across Cayenne.
 
 @author Andrei Adamchik
 */
public class Util {
  /**
   * Creates an XMLReader with default feature set. Note that all Cayenne internal XML
   * parsers should probably use XMLReader obtained via this method for consistency
   * sake, and can customize feature sets as needed.
   */
  public static XMLReader createXmlReader() throws SAXException,
          ParserConfigurationException {
      SAXParserFactory spf = SAXParserFactory.newInstance();

      // Create a JAXP SAXParser
      SAXParser saxParser = spf.newSAXParser();

      // Get the encapsulated SAX XMLReader
      XMLReader reader = saxParser.getXMLReader();

      // set default features
      reader.setFeature("http://xml.org/sax/features/namespaces"true);

      return reader;
  }
}

   
    
    
  

Utility class for xml/sax handling

   
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

import java.io.*;
import java.util.*;

import javax.xml.transform.*;
import javax.xml.transform.sax.*;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.xml.sax.*;
import org.xml.sax.helpers.AttributesImpl;

/**
 * Utility class for xml/sax handling.
 * It provides support for "older" sax implementations (like the default one shipped with JDK 1.4.2)
 * which have bugs in the namespace handling.
 */
public class IOUtils {

    /** The transformer factory. */
    private static final SAXTransformerFactory FACTORY = (SAXTransformerFactoryTransformerFactory.newInstance();

    /** The URI for xml namespaces */
    private static final String XML_NAMESPACE_URI = "http://www.w3.org/XML/1998/namespace";

    /**
     * Parse a file and send the sax events to the content handler.
     @param file
     @param handler
     @throws IOException
     @throws TransformerException
     */
    public static final void parse(File file, ContentHandler handler)
    throws IOException, TransformerException {
        final Transformer transformer = FACTORY.newTransformer();
        transformer.transform(new StreamSource(new FileReader(file)),
                new SAXResult(handler));
    }

    public static ContentHandler getSerializer(File file)
    throws IOException, TransformerException {
        final FileWriter writer = new FileWriter(file);

        final TransformerHandler transformerHandler = FACTORY.newTransformerHandler();
        final Transformer transformer = transformerHandler.getTransformer();

        final Properties format = new Properties();
        format.put(OutputKeys.METHOD, "xml");
        format.put(OutputKeys.OMIT_XML_DECLARATION, "no");
        format.put(OutputKeys.ENCODING, "UTF-8");
        format.put(OutputKeys.INDENT, "yes");
        transformer.setOutputProperties(format);

        transformerHandler.setResult(new StreamResult(writer));

        try {
            if needsNamespacesAsAttributes(format) ) {
                return new NamespaceAsAttributes(transformerHandler);
            }
        catch (SAXException se) {
            throw new TransformerException("Unable to detect of namespace support for sax works properly.", se);
        }
        return transformerHandler;
    }

    /**
     * Checks if the used Trax implementation correctly handles namespaces set using
     * <code>startPrefixMapping()</code>, but wants them also as 'xmlns:' attributes.
     * <p>
     * The check consists in sending SAX events representing a minimal namespaced document
     * with namespaces defined only with calls to <code>startPrefixMapping</code> (no
     * xmlns:xxx attributes) and check if they are present in the resulting text.
     */
    protected static boolean needsNamespacesAsAttributes(Properties format)
    throws TransformerException, SAXException {
        // Serialize a minimal document to check how namespaces are handled.
        final StringWriter writer = new StringWriter();

        final String uri = "namespaceuri";
        final String prefix = "nsp";
        final String check = "xmlns:" + prefix + "='" + uri + "'";

        final TransformerHandler handler = FACTORY.newTransformerHandler();

        handler.getTransformer().setOutputProperties(format);
        handler.setResult(new StreamResult(writer));

        // Output a single element
        handler.startDocument();
        handler.startPrefixMapping(prefix, uri);
        handler.startElement(uri, "element""element"new AttributesImpl());
        handler.endElement(uri, "element""element");
        handler.endPrefixMapping(prefix);
        handler.endDocument();

        final String text = writer.toString();

        // Check if the namespace is there (replace " by ' to be sure of what we search in)
        boolean needsIt = (text.replace('"''\'').indexOf(check== -1);

        return needsIt;
    }

    /**
     * A pipe that ensures that all namespace prefixes are also present as
     * 'xmlns:' attributes. This used to circumvent Xalan's serialization behaviour
     * which is to ignore namespaces if they're not present as 'xmlns:xxx' attributes.
     */
    public static class NamespaceAsAttributes implements ContentHandler {

        /** The wrapped content handler. */
        private final ContentHandler contentHandler;

        /**
         * The prefixes of startPrefixMapping() declarations for the coming element.
         */
        private List prefixList = new ArrayList();

        /**
         * The URIs of startPrefixMapping() declarations for the coming element.
         */
        private List uriList = new ArrayList();

        /**
         * Maps of URI<->prefix mappings. Used to work around a bug in the Xalan
         * serializer.
         */
        private Map uriToPrefixMap = new HashMap();
        private Map prefixToUriMap = new HashMap();

        /**
         * True if there has been some startPrefixMapping() for the coming element.
         */
        private boolean hasMappings = false;

        public NamespaceAsAttributes(ContentHandler ch) {
            this.contentHandler = ch;
        }

        public void startDocument() throws SAXException {
            // Cleanup
            this.uriToPrefixMap.clear();
            this.prefixToUriMap.clear();
            clearMappings();
            this.contentHandler.startDocument();
        }

        /**
         * Track mappings to be able to add <code>xmlns:</code> attributes
         * in <code>startElement()</code>.
         */
        public void startPrefixMapping(String prefix, String urithrows SAXException {
            // Store the mappings to reconstitute xmlns:attributes
            // except prefixes starting with "xml": these are reserved
            // VG: (uri != null) fixes NPE in startElement
            if (uri != null && !prefix.startsWith("xml")) {
                this.hasMappings = true;
                this.prefixList.add(prefix);
                this.uriList.add(uri);

                // append the prefix colon now, in order to save concatenations later, but
                // only for non-empty prefixes.
                if (prefix.length() 0) {
                    this.uriToPrefixMap.put(uri, prefix + ":");
                else {
                    this.uriToPrefixMap.put(uri, prefix);
                }

                this.prefixToUriMap.put(prefix, uri);
            }
            this.contentHandler.startPrefixMapping(prefix, uri);
        }

        /**
         * Ensure all namespace declarations are present as <code>xmlns:</code> attributes
         * and add those needed before calling superclass. This is a workaround for a Xalan bug
         * (at least in version 2.0.1) : <code>org.apache.xalan.serialize.SerializerToXML</code>
         * ignores <code>start/endPrefixMapping()</code>.
         */
        public void startElement(String eltUri, String eltLocalName, String eltQName, Attributes attrs)
                throws SAXException {

            // try to restore the qName. The map already contains the colon
            if (null != eltUri && eltUri.length() != && this.uriToPrefixMap.containsKey(eltUri)) {
                eltQName = this.uriToPrefixMap.get(eltUri+ eltLocalName;
            }
            if (this.hasMappings) {
                // Add xmlns* attributes where needed

                // New Attributes if we have to add some.
                AttributesImpl newAttrs = null;

                int mappingCount = this.prefixList.size();
                int attrCount = attrs.getLength();

                for (int mapping = 0; mapping < mappingCount; mapping++) {

                    // Build infos for this namespace
                    String uri = (Stringthis.uriList.get(mapping);
                    String prefix = (Stringthis.prefixList.get(mapping);
                    String qName = prefix.length() == "xmlns" ("xmlns:" + prefix);

                    // Search for the corresponding xmlns* attribute
                    boolean found = false;
                    for (int attr = 0; attr < attrCount; attr++) {
                        if (qName.equals(attrs.getQName(attr))) {
                            // Check if mapping and attribute URI match
                            if (!uri.equals(attrs.getValue(attr))) {
                                throw new SAXException("URI in prefix mapping and attribute do not match");
                            }
                            found = true;
                            break;
                        }
                    }

                    if (!found) {
                        // Need to add this namespace
                        if (newAttrs == null) {
                            // Need to test if attrs is empty or we go into an infinite loop...
                            // Well know SAX bug which I spent 3 hours to remind of :-(
                            if (attrCount == 0) {
                                newAttrs = new AttributesImpl();
                            else {
                                newAttrs = new AttributesImpl(attrs);
                            }
                        }

                        if (prefix.length() == 0) {
                            newAttrs.addAttribute(XML_NAMESPACE_URI, "xmlns""xmlns""CDATA", uri);
                        else {
                            newAttrs.addAttribute(XML_NAMESPACE_URI, prefix, qName, "CDATA", uri);
                        }
                    }
                // end for mapping

                // Cleanup for the next element
                clearMappings();

                // Start element with new attributes, if any
                this.contentHandler.startElement(eltUri, eltLocalName, eltQName, newAttrs == null ? attrs : newAttrs);
            else {
                // Normal job
                this.contentHandler.startElement(eltUri, eltLocalName, eltQName, attrs);
            }
        }


        /**
         * Receive notification of the end of an element.
         * Try to restore the element qName.
         */
        public void endElement(String eltUri, String eltLocalName, String eltQNamethrows SAXException {
            // try to restore the qName. The map already contains the colon
            if (null != eltUri && eltUri.length() != && this.uriToPrefixMap.containsKey(eltUri)) {
                eltQName = this.uriToPrefixMap.get(eltUri+ eltLocalName;
            }
            this.contentHandler.endElement(eltUri, eltLocalName, eltQName);
        }

        /**
         * End the scope of a prefix-URI mapping:
         * remove entry from mapping tables.
         */
        public void endPrefixMapping(String prefixthrows SAXException {
            // remove mappings for xalan-bug-workaround.
            // Unfortunately, we're not passed the uri, but the prefix here,
            // so we need to maintain maps in both directions.
            if (this.prefixToUriMap.containsKey(prefix)) {
                this.uriToPrefixMap.remove(this.prefixToUriMap.get(prefix));
                this.prefixToUriMap.remove(prefix);
            }

            if (hasMappings) {
                // most of the time, start/endPrefixMapping calls have an element event between them,
                // which will clear the hasMapping flag and so this code will only be executed in the
                // rather rare occasion when there are start/endPrefixMapping calls with no element
                // event in between. If we wouldn't remove the items from the prefixList and uriList here,
                // the namespace would be incorrectly declared on the next&n

XML utility methods that only depend on the JDK

   
/*
 * StandardUtilities.java - Miscelaneous XML utility functions.
 * :tabSize=8:indentSize=8:noTabs=false:
 * :folding=explicit:collapseFolds=1:
 *
 * Copyright (C) 1999, 2006 Marcelo Vanzin, Slava Pestov
 * Portions copyright (C) 2000 Richard S. Hall
 * Portions copyright (C) 2001 Dirk Moebius
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */



//{{{ Imports
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.io.IOException;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
//}}}

/**
 * XML utility methods that only depend on the JDK.
 *
 @author Marcelo Vanzin
 @version $Id: XMLUtilities.java 13929 2008-10-25 14:23:41Z k_satoda $
 @since 4.3pre6
 */
public class XMLUtilities
{

  //{{{ charsToEntities() method
  /**
   * Converts &lt;, &gt;, &amp; in the string to their HTML entity
   * equivalents.
   *
   * <p>If <code>xml11</code> is true, then character entities
   * are used to convert illegal XML characters (mainly ASCII
   * control characters).</p>
   *
   @param str The string
   @param xml11 Whether to allow XML 1.1 constructs.
   */
  public static String charsToEntities(String str, boolean xml11)
  {
    StringBuilder buf = new StringBuilder(str.length());
    for(int i = 0; i < str.length(); i++)
    {
      char ch = str.charAt(i);

      // control characters, excluding \t, \r and \n
      // See: http://www.w3.org/International/questions/qa-controls
      if (((0x00 <= ch && ch <= 0x1F|| (0x7F <= ch && ch <= 0x9F))
        && ch != '\r' && ch != '\n' && ch != '\t')
      {
        if (xml11 && ch != 0x00)
        {
          buf.append("&#").append((int)ch).append(';');
        }
        else
        {
          // The character is illegal.
          // But put a PI instead, to make it
          // recoverable in certain apps.
          buf.append("<?illegal-xml-character ")
            .append((int)ch)
            .append("?>");
        }
        continue;
      }

      switch(ch)
      {
      case '<':
        buf.append("&lt;");
        break;
      case '>':
        buf.append("&gt;");
        break;
      case '&':
        buf.append("&amp;");
        break;
      default:
        buf.append(ch);
        break;
      }
    }
    return buf.toString();
  //}}}

  //{{{ parseXML() method
  /**
   * Convenience method for parsing an XML file. This method will
   * wrap the resource in an InputSource and set the source's
   * systemId to "jedit.jar" (so the source should be able to
   * handle any external entities by itself).
   *
   * <p>SAX Errors are caught and are not propagated to the caller;
   * instead, an error message is printed to jEdit's activity
   * log. So, if you need custom error handling, <b>do not use
   * this method</b>.
   *
   * <p>The given stream is closed before the method returns,
   * regardless whether there were errors or not.</p>
   *
   @return true if any error occured during parsing, false if success.
   */
  public static boolean parseXML(InputStream in, DefaultHandler handler)
    throws IOException
  {
    try
    {
      XMLReader parser = XMLReaderFactory.createXMLReader();
      InputSource isrc = new InputSource(
        new BufferedInputStream(in));
      isrc.setSystemId("jedit.jar");
      parser.setContentHandler(handler);
      parser.setDTDHandler(handler);
      parser.setEntityResolver(handler);
      parser.setErrorHandler(handler);
      parser.parse(isrc);
    }
    catch(SAXParseException se)
    {
      int line = se.getLineNumber();
      return true;
    }
    catch(SAXException e)
    {
      return true;
    }
    finally
    {
      try
      {
        if(in != null)
          in.close();
      }
      catch(IOException io)
      {
      }
    }
    return false;
  //}}}

  //{{{ resolveEntity() method
  /**
   * Tries to find the given systemId in the context of the given
   * class. If the given systemId ends with the given test string,
   * then try to load a resource using the Class's
   * <code>getResourceAsStream()</code> method using the test string
   * as the resource.
   *
   * <p>This is used a lot internally while parsing XML files used
   * by jEdit, but anyone is free to use the method if it sounds
   * usable.</p>
   */
  public static InputSource findEntity(String systemId, String test, Class where)
  {
    if (systemId != null && systemId.endsWith(test))
    {
      try
      {
        return new InputSource(new BufferedInputStream(
          where.getResourceAsStream(test)));
      }
      catch (Exception e)
      {
      }
    }

    return null;
  //}}}

  private XMLUtilities() { }
}