001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.core.filesystems;
043:
044: import java.io.*;
045: import java.util.logging.Level;
046: import java.util.logging.Logger;
047:
048: import org.xml.sax.*;
049: import org.xml.sax.helpers.*;
050: import org.openide.filesystems.*;
051: import org.openide.util.*;
052: import org.openide.xml.*;
053: import org.openide.*;
054:
055: /**
056: * Implements default interruptible silent parser behaviour.
057: * Errors can be tested by quering parser state.
058: *
059: * @author Petr Kuzel
060: * @version 1.0
061: */
062: abstract class DefaultParser extends DefaultHandler {
063:
064: protected FileObject fo;
065: private Locator locator = null;
066:
067: protected short state = INIT;
068:
069: protected static final short PARSED = 1000;
070: protected static final short ERROR = -1;
071: protected static final short INIT = 0;
072:
073: protected DefaultParser() {
074: }
075:
076: protected DefaultParser(FileObject fo) {
077: this .fo = fo;
078: }
079:
080: /**
081: * Preconfigure parser and return it.
082: */
083: protected XMLReader createXMLReader() throws IOException,
084: SAXException {
085: return XMLUtil.createXMLReader(false);
086: }
087:
088: /**
089: * Check if the given exception is one thrown from the handler
090: * for stopping the parser.
091: */
092: protected boolean isStopException(Exception e) {
093: return false;
094: }
095:
096: /**
097: * @return current parser state
098: */
099: protected short getState() {
100: return state;
101: }
102:
103: protected final Locator getLocator() {
104: return locator;
105: }
106:
107: /**
108: * Parser content workarounding known parser implementation
109: * problems.
110: */
111: protected void parse(FileObject fo) {
112: state = INIT; // #15672
113: InputStream is = null;
114: this .fo = fo;
115: try {
116: XMLReader parser = createXMLReader();
117: parser.setEntityResolver(this );
118: parser.setErrorHandler(this );
119: parser.setContentHandler(this );
120:
121: // try {
122: // // do not read DTD
123: // parser.setFeature("http://xml.org/sax/features/external-parameter-entities", false); //NOI18N
124: // } catch (SAXException ignore) {
125: // // parsing may be slower :-(
126: // }
127:
128: InputSource in = new InputSource();
129: is = fo.getInputStream();
130: in.setByteStream(is);
131: in.setSystemId(fo.getURL().toExternalForm());
132: customizeInputSource(in);
133:
134: parser.parse(in);
135:
136: } catch (IOException io) {
137: if (!isStopException(io)) {
138: if (fo.isValid() && fo.canRead()) {
139: Exceptions
140: .attachMessage(io, "While parsing: " + fo); // NOI18N
141: Logger.getLogger(DefaultParser.class.getName())
142: .log(Level.INFO, null, io);
143: state = ERROR;
144: }
145: }
146: } catch (SAXException sex) {
147: if (!isStopException(sex)) {
148: Exceptions.attachMessage(sex, "While parsing: " + fo); // NOI18N
149: Logger.getLogger(DefaultParser.class.getName()).log(
150: Level.INFO, null, sex);
151: state = ERROR;
152: }
153: } finally {
154: if (is != null) {
155: try {
156: is.close();
157: } catch (IOException ex) {
158: // already closed
159: }
160: }
161: }
162: }
163:
164: protected void customizeInputSource(InputSource in) {
165: }
166:
167: /**
168: * Parser default file object
169: */
170: protected final void parse() {
171: if (fo == null)
172: throw new NullPointerException();
173: parse(fo);
174: }
175:
176: /** Report error occured during custom validation. */
177: protected void error() throws SAXException {
178: String reason = org.openide.util.NbBundle.getMessage(
179: DefaultParser.class, "Invalid_XML_document");
180: error(reason);
181: }
182:
183: /** Report error occured during custom validation. */
184: protected void error(String reason) throws SAXException {
185: StringBuffer buf = new StringBuffer(reason).append(": ")
186: .append(fo.toString());//NOI18N
187: if (locator != null) {
188: buf.append(" line: ").append(locator.getLineNumber());//NOI18N
189: buf.append(" column: ").append(locator.getColumnNumber());//NOI18N
190: }
191: String msg = buf.toString(); //NOI18N
192: SAXException sex = new SAXException(msg);
193: throw sex;
194: }
195:
196: public void error(SAXParseException exception) throws SAXException {
197: throw exception;
198: }
199:
200: public void fatalError(SAXParseException exception)
201: throws SAXException {
202: throw exception;
203: }
204:
205: public void endDocument() throws SAXException {
206: state = PARSED;
207: }
208:
209: public void setDocumentLocator(Locator locator) {
210: this .locator = locator;
211: }
212:
213: public InputSource resolveEntity(String publicID, String systemID) {
214: // Read nothing whatsoever.
215: return new InputSource(new ByteArrayInputStream(new byte[] {}));
216: }
217:
218: }
|