001: /*
002: * StandardUtilities.java - Miscelaneous XML utility functions.
003: * :tabSize=8:indentSize=8:noTabs=false:
004: * :folding=explicit:collapseFolds=1:
005: *
006: * Copyright (C) 1999, 2006 Marcelo Vanzin, Slava Pestov
007: * Portions copyright (C) 2000 Richard S. Hall
008: * Portions copyright (C) 2001 Dirk Moebius
009: *
010: * This program is free software; you can redistribute it and/or
011: * modify it under the terms of the GNU General Public License
012: * as published by the Free Software Foundation; either version 2
013: * of the License, or any later version.
014: *
015: * This program is distributed in the hope that it will be useful,
016: * but WITHOUT ANY WARRANTY; without even the implied warranty of
017: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
018: * GNU General Public License for more details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with this program; if not, write to the Free Software
022: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
023: */
024:
025: package org.gjt.sp.util;
026:
027: import java.io.InputStream;
028: import java.io.BufferedInputStream;
029: import java.io.IOException;
030: import java.io.Reader;
031:
032: import org.xml.sax.InputSource;
033: import org.xml.sax.SAXException;
034: import org.xml.sax.SAXParseException;
035: import org.xml.sax.XMLReader;
036: import org.xml.sax.helpers.DefaultHandler;
037: import org.xml.sax.helpers.XMLReaderFactory;
038:
039: /**
040: * XML utility methods that only depend on the JDK.
041: *
042: * @author Marcelo Vanzin
043: * @version $Id: XMLUtilities.java 10892 2007-10-14 10:54:49Z k_satoda $
044: * @since 4.3pre6
045: */
046: public class XMLUtilities {
047:
048: //{{{ charsToEntities() method
049: /**
050: * Converts <, >, & in the string to their HTML entity
051: * equivalents.
052: *
053: * <p>If <code>xml11</code> is true, then character entities
054: * are used to convert illegal XML characters (mainly ASCII
055: * control characters).</p>
056: *
057: * @param str The string
058: * @param xml11 Whether to allow XML 1.1 constructs.
059: */
060: public static String charsToEntities(String str, boolean xml11) {
061: StringBuffer buf = new StringBuffer(str.length());
062: for (int i = 0; i < str.length(); i++) {
063: char ch = str.charAt(i);
064:
065: // control characters, excluding \t, \r and \n
066: if (xml11 && ch < 32 && ch != '\r' && ch != '\n'
067: && ch != '\t') {
068: buf.append("&#").append((int) ch).append(";");
069: continue;
070: }
071:
072: switch (ch) {
073: case '<':
074: buf.append("<");
075: break;
076: case '>':
077: buf.append(">");
078: break;
079: case '&':
080: buf.append("&");
081: break;
082: default:
083: buf.append(ch);
084: break;
085: }
086: }
087: return buf.toString();
088: } //}}}
089:
090: //{{{ parseXML() method
091: /**
092: * Convenience method for parsing an XML file. This method will
093: * wrap the resource in an InputSource and set the source's
094: * systemId to "jedit.jar" (so the source should be able to
095: * handle any external entities by itself).
096: *
097: * <p>SAX Errors are caught and are not propagated to the caller;
098: * instead, an error message is printed to jEdit's activity
099: * log. So, if you need custom error handling, <b>do not use
100: * this method</b>.
101: *
102: * <p>The given stream is closed before the method returns,
103: * regardless whether there were errors or not.</p>
104: *
105: * @return true if any error occured during parsing, false if success.
106: */
107: public static boolean parseXML(InputStream in,
108: DefaultHandler handler) throws IOException {
109: try {
110: XMLReader parser = XMLReaderFactory.createXMLReader();
111: InputSource isrc = new InputSource(new BufferedInputStream(
112: in));
113: isrc.setSystemId("jedit.jar");
114: parser.setContentHandler(handler);
115: parser.setDTDHandler(handler);
116: parser.setEntityResolver(handler);
117: parser.setErrorHandler(handler);
118: parser.parse(isrc);
119: } catch (SAXParseException se) {
120: int line = se.getLineNumber();
121: String message = se.getMessage();
122: Log.log(Log.ERROR, XMLUtilities.class,
123: "while parsing from " + in
124: + ": SAXParseException: line " + line
125: + ": ", se);
126: return true;
127: } catch (SAXException e) {
128: Log.log(Log.ERROR, XMLUtilities.class, e);
129: return true;
130: } finally {
131: try {
132: if (in != null)
133: in.close();
134: } catch (IOException io) {
135: Log.log(Log.ERROR, XMLUtilities.class, io);
136: }
137: }
138: return false;
139: } //}}}
140:
141: //{{{ resolveEntity() method
142: /**
143: * Tries to find the given systemId in the context of the given
144: * class. If the given systemId ends with the given test string,
145: * then try to load a resource using the Class's
146: * <code>getResourceAsStream()</code> method using the test string
147: * as the resource.
148: *
149: * <p>This is used a lot internally while parsing XML files used
150: * by jEdit, but anyone is free to use the method if it sounds
151: * usable.</p>
152: */
153: public static InputSource findEntity(String systemId, String test,
154: Class where) {
155: if (systemId != null && systemId.endsWith(test)) {
156: try {
157: return new InputSource(new BufferedInputStream(where
158: .getResourceAsStream(test)));
159: } catch (Exception e) {
160: Log.log(Log.ERROR, XMLUtilities.class,
161: "Error while opening " + test + ":");
162: Log.log(Log.ERROR, XMLUtilities.class, e);
163: }
164: }
165:
166: return null;
167: } //}}}
168:
169: private XMLUtilities() {
170: }
171: }
|