/**
*
* 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;
}
}
sources68 the directory containing the programming examples, source code and programming guide online
Sunday, 31 July 2011
Create Xml 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 = (SAXTransformerFactory) TransformerFactory.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 uri) throws 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() != 0 && 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 = (String) this.uriList.get(mapping);
String prefix = (String) this.prefixList.get(mapping);
String qName = prefix.length() == 0 ? "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 eltQName) throws SAXException {
// try to restore the qName. The map already contains the colon
if (null != eltUri && eltUri.length() != 0 && 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 prefix) throws 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 <, >, & 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("<");
break;
case '>':
buf.append(">");
break;
case '&':
buf.append("&");
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() { }
}
Subscribe to:
Posts (Atom)