286N/A/*
286N/A * reserved comment block
286N/A * DO NOT REMOVE OR ALTER!
286N/A */
286N/A// TextCatalogReader.java - Read text/plain Catalog files
286N/A
286N/A/*
286N/A * Copyright 2001-2004 The Apache Software Foundation or its licensors,
286N/A * as applicable.
286N/A *
286N/A * Licensed under the Apache License, Version 2.0 (the "License");
286N/A * you may not use this file except in compliance with the License.
286N/A * You may obtain a copy of the License at
286N/A *
286N/A * http://www.apache.org/licenses/LICENSE-2.0
286N/A *
286N/A * Unless required by applicable law or agreed to in writing, software
286N/A * distributed under the License is distributed on an "AS IS" BASIS,
286N/A * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
286N/A * See the License for the specific language governing permissions and
286N/A * limitations under the License.
286N/A */
286N/A
286N/Apackage com.sun.org.apache.xml.internal.resolver.readers;
286N/A
286N/Aimport java.io.InputStream;
286N/Aimport java.io.IOException;
286N/Aimport java.io.FileNotFoundException;
286N/Aimport java.net.URL;
286N/Aimport java.net.URLConnection;
286N/Aimport java.net.MalformedURLException;
286N/Aimport java.util.Vector;
286N/Aimport java.util.Stack;
286N/Aimport com.sun.org.apache.xml.internal.resolver.Catalog;
286N/Aimport com.sun.org.apache.xml.internal.resolver.CatalogEntry;
286N/Aimport com.sun.org.apache.xml.internal.resolver.CatalogException;
286N/Aimport com.sun.org.apache.xml.internal.resolver.readers.CatalogReader;
286N/A
286N/A/**
286N/A * Parses plain text Catalog files.
286N/A *
286N/A * <p>This class reads plain text Open Catalog files.</p>
286N/A *
286N/A * @see Catalog
286N/A *
286N/A * @author Norman Walsh
286N/A * <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
286N/A *
286N/A */
286N/Apublic class TextCatalogReader implements CatalogReader {
286N/A /** The input stream used to read the catalog */
286N/A protected InputStream catfile = null;
286N/A
286N/A /**
286N/A * Character lookahead stack. Reading a catalog sometimes requires
286N/A * up to two characters of lookahead.
286N/A */
286N/A protected int[] stack = new int[3];
286N/A
286N/A /**
286N/A * Token stack. Recognizing an unexpected catalog entry requires
286N/A * the ability to "push back" a token.
286N/A */
286N/A protected Stack tokenStack = new Stack();
286N/A
286N/A /** The current position on the lookahead stack */
286N/A protected int top = -1;
286N/A
286N/A /** Are keywords in the catalog case sensitive? */
286N/A protected boolean caseSensitive = false;
286N/A
286N/A /**
286N/A * Construct a CatalogReader object.
286N/A */
286N/A public TextCatalogReader() { }
286N/A
286N/A public void setCaseSensitive(boolean isCaseSensitive) {
286N/A caseSensitive = isCaseSensitive;
286N/A }
286N/A
286N/A public boolean getCaseSensitive() {
286N/A return caseSensitive;
286N/A }
286N/A
286N/A /**
286N/A * Start parsing a text catalog file. The file is
286N/A * actually read and parsed
286N/A * as needed by <code>nextEntry</code>.</p>
286N/A *
286N/A * @param fileUrl The URL or filename of the catalog file to process
286N/A *
286N/A * @throws MalformedURLException Improper fileUrl
286N/A * @throws IOException Error reading catalog file
286N/A */
286N/A public void readCatalog(Catalog catalog, String fileUrl)
286N/A throws MalformedURLException, IOException {
286N/A URL catURL = null;
286N/A
286N/A try {
286N/A catURL = new URL(fileUrl);
286N/A } catch (MalformedURLException e) {
286N/A catURL = new URL("file:///" + fileUrl);
286N/A }
286N/A
286N/A URLConnection urlCon = catURL.openConnection();
286N/A try {
286N/A readCatalog(catalog, urlCon.getInputStream());
286N/A } catch (FileNotFoundException e) {
286N/A catalog.getCatalogManager().debug.message(1, "Failed to load catalog, file not found",
286N/A catURL.toString());
286N/A }
286N/A }
286N/A
286N/A public void readCatalog(Catalog catalog, InputStream is)
286N/A throws MalformedURLException, IOException {
286N/A
286N/A catfile = is;
286N/A
286N/A if (catfile == null) {
286N/A return;
286N/A }
286N/A
286N/A Vector unknownEntry = null;
286N/A
286N/A try {
286N/A while (true) {
286N/A String token = nextToken();
286N/A
286N/A if (token == null) {
286N/A if (unknownEntry != null) {
286N/A catalog.unknownEntry(unknownEntry);
286N/A unknownEntry = null;
286N/A }
286N/A catfile.close();
286N/A catfile = null;
286N/A return;
286N/A }
286N/A
286N/A String entryToken = null;
286N/A if (caseSensitive) {
286N/A entryToken = token;
286N/A } else {
286N/A entryToken = token.toUpperCase();
286N/A }
286N/A
286N/A try {
286N/A int type = CatalogEntry.getEntryType(entryToken);
286N/A int numArgs = CatalogEntry.getEntryArgCount(type);
286N/A Vector args = new Vector();
286N/A
286N/A if (unknownEntry != null) {
286N/A catalog.unknownEntry(unknownEntry);
286N/A unknownEntry = null;
286N/A }
286N/A
286N/A for (int count = 0; count < numArgs; count++) {
286N/A args.addElement(nextToken());
286N/A }
286N/A
286N/A catalog.addEntry(new CatalogEntry(entryToken, args));
286N/A } catch (CatalogException cex) {
286N/A if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
286N/A if (unknownEntry == null) {
286N/A unknownEntry = new Vector();
286N/A }
286N/A unknownEntry.addElement(token);
286N/A } else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
286N/A catalog.getCatalogManager().debug.message(1, "Invalid catalog entry", token);
286N/A unknownEntry = null;
286N/A } else if (cex.getExceptionType() == CatalogException.UNENDED_COMMENT) {
286N/A catalog.getCatalogManager().debug.message(1, cex.getMessage());
286N/A }
286N/A }
286N/A }
286N/A } catch (CatalogException cex2) {
286N/A if (cex2.getExceptionType() == CatalogException.UNENDED_COMMENT) {
286N/A catalog.getCatalogManager().debug.message(1, cex2.getMessage());
286N/A }
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * The destructor.
286N/A *
286N/A * <p>Makes sure the catalog file is closed.</p>
286N/A */
286N/A protected void finalize() {
286N/A if (catfile != null) {
286N/A try {
286N/A catfile.close();
286N/A } catch (IOException e) {
286N/A // whatever...
286N/A }
286N/A }
286N/A catfile = null;
286N/A }
286N/A
286N/A // -----------------------------------------------------------------
286N/A
286N/A /**
286N/A * Return the next token in the catalog file.
286N/A *
286N/A * <p>FYI: This code does not throw any sort of exception for
286N/A * a file that contains an n
286N/A *
286N/A * @return The Catalog file token from the input stream.
286N/A * @throws IOException If an error occurs reading from the stream.
286N/A */
286N/A protected String nextToken() throws IOException, CatalogException {
286N/A String token = "";
286N/A int ch, nextch;
286N/A
286N/A if (!tokenStack.empty()) {
286N/A return (String) tokenStack.pop();
286N/A }
286N/A
286N/A // Skip over leading whitespace and comments
286N/A while (true) {
286N/A // skip leading whitespace
286N/A ch = catfile.read();
286N/A while (ch <= ' ') { // all ctrls are whitespace
286N/A ch = catfile.read();
286N/A if (ch < 0) {
286N/A return null;
286N/A }
286N/A }
286N/A
286N/A // now 'ch' is the current char from the file
286N/A nextch = catfile.read();
286N/A if (nextch < 0) {
286N/A return null;
286N/A }
286N/A
286N/A if (ch == '-' && nextch == '-') {
286N/A // we've found a comment, skip it...
286N/A ch = ' ';
286N/A nextch = nextChar();
286N/A while ((ch != '-' || nextch != '-') && nextch > 0) {
286N/A ch = nextch;
286N/A nextch = nextChar();
286N/A }
286N/A
286N/A if (nextch < 0) {
286N/A throw new CatalogException(CatalogException.UNENDED_COMMENT,
286N/A "Unterminated comment in catalog file; EOF treated as end-of-comment.");
286N/A }
286N/A
286N/A // Ok, we've found the end of the comment,
286N/A // loop back to the top and start again...
286N/A } else {
286N/A stack[++top] = nextch;
286N/A stack[++top] = ch;
286N/A break;
286N/A }
286N/A }
286N/A
286N/A ch = nextChar();
286N/A if (ch == '"' || ch == '\'') {
286N/A int quote = ch;
286N/A while ((ch = nextChar()) != quote) {
286N/A char[] chararr = new char[1];
286N/A chararr[0] = (char) ch;
286N/A String s = new String(chararr);
286N/A token = token.concat(s);
286N/A }
286N/A return token;
286N/A } else {
286N/A // return the next whitespace or comment delimited
286N/A // string
286N/A while (ch > ' ') {
286N/A nextch = nextChar();
286N/A if (ch == '-' && nextch == '-') {
286N/A stack[++top] = ch;
286N/A stack[++top] = nextch;
286N/A return token;
286N/A } else {
286N/A char[] chararr = new char[1];
286N/A chararr[0] = (char) ch;
286N/A String s = new String(chararr);
286N/A token = token.concat(s);
286N/A ch = nextch;
286N/A }
286N/A }
286N/A return token;
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Return the next logical character from the input stream.
286N/A *
286N/A * @return The next (logical) character from the input stream. The
286N/A * character may be buffered from a previous lookahead.
286N/A *
286N/A * @throws IOException If an error occurs reading from the stream.
286N/A */
286N/A protected int nextChar() throws IOException {
286N/A if (top < 0) {
286N/A return catfile.read();
286N/A } else {
286N/A return stack[top--];
286N/A }
286N/A }
286N/A}