Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
206 lines
6 KiB
Java
206 lines
6 KiB
Java
/*
|
|
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation. Oracle designates this
|
|
* particular file as subject to the "Classpath" exception as provided
|
|
* by Oracle in the LICENSE file that accompanied this code.
|
|
*
|
|
* This code 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
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
package build.tools.dtdbuilder;
|
|
|
|
import javax.swing.text.html.parser.*;
|
|
import java.io.IOException;
|
|
import java.io.FileInputStream;
|
|
import java.io.InputStream;
|
|
import java.io.Reader;
|
|
import java.io.InputStreamReader;
|
|
import java.io.CharArrayReader;
|
|
import java.io.FilterReader;
|
|
import java.util.Stack;
|
|
import java.net.URL;
|
|
|
|
/**
|
|
* A stream for reading HTML files. This stream takes care
|
|
* of \r\n conversions and parameter entity expansion.
|
|
*
|
|
* @see DTD
|
|
* @see DTDParser
|
|
* @author Arthur van Hoff
|
|
* @author Steven B. Byrne
|
|
*/
|
|
public final
|
|
class DTDInputStream extends FilterReader implements DTDConstants {
|
|
public DTD dtd;
|
|
public Stack<Object> stack = new Stack<>();
|
|
public char str[] = new char[64];
|
|
public int replace = 0;
|
|
public int ln = 1;
|
|
public int ch;
|
|
|
|
/**
|
|
* Create the stream.
|
|
*/
|
|
public DTDInputStream(InputStream in, DTD dtd) throws IOException {
|
|
super(new InputStreamReader(in));
|
|
this.dtd = dtd;
|
|
this.ch = in.read();
|
|
}
|
|
|
|
/**
|
|
* Error
|
|
*/
|
|
public void error(String msg) {
|
|
System.out.println("line " + ln + ": dtd input error: " + msg);
|
|
}
|
|
|
|
/**
|
|
* Push a single character
|
|
*/
|
|
public void push(int ch) throws IOException {
|
|
char data[] = {(char)ch};
|
|
push(new CharArrayReader(data));
|
|
}
|
|
|
|
|
|
/**
|
|
* Push an array of bytes.
|
|
*/
|
|
public void push(char data[]) throws IOException {
|
|
if (data.length > 0) {
|
|
push(new CharArrayReader(data));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Push an entire input stream
|
|
*/
|
|
void push(Reader in) throws IOException {
|
|
stack.push(Integer.valueOf(ln));
|
|
stack.push(Integer.valueOf(ch));
|
|
stack.push(this.in);
|
|
this.in = in;
|
|
ch = in.read();
|
|
}
|
|
|
|
/**
|
|
* Read a character from the input. Automatically pop
|
|
* a stream of the stack if the EOF is reached. Also replaces
|
|
* parameter entities.
|
|
* [60] 350:22
|
|
*/
|
|
@SuppressWarnings("fallthrough")
|
|
public int read() throws IOException {
|
|
switch (ch) {
|
|
case '%': {
|
|
ch = in.read();
|
|
if (replace > 0) {
|
|
return '%';
|
|
}
|
|
|
|
int pos = 0;
|
|
while (((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) ||
|
|
((ch >= '0') && (ch <= '9')) || (ch == '.') || (ch == '-')) {
|
|
str[pos++] = (char)ch;
|
|
ch = in.read();
|
|
}
|
|
if (pos == 0) {
|
|
return '%';
|
|
}
|
|
|
|
String nm = new String(str, 0, pos);
|
|
Entity ent = dtd.getEntity(nm);
|
|
if (ent == null) {
|
|
error("undefined entity reference: " + nm);
|
|
return read();
|
|
}
|
|
|
|
// Skip ; or RE
|
|
switch (ch) {
|
|
case '\r':
|
|
ln++;
|
|
/* fall through */
|
|
case ';':
|
|
ch = in.read();
|
|
break;
|
|
case '\n':
|
|
ln++;
|
|
if ((ch = in.read()) == '\r') {
|
|
ch = in.read();
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Push the entity.
|
|
try {
|
|
push(getEntityInputReader(ent));
|
|
} catch (Exception e) {
|
|
error("entity data not found: " + ent + ", " + ent.getString());
|
|
}
|
|
return read();
|
|
}
|
|
|
|
case '\n':
|
|
ln++;
|
|
if ((ch = in.read()) == '\r') {
|
|
ch = in.read();
|
|
}
|
|
return '\n';
|
|
|
|
case '\r':
|
|
ln++;
|
|
ch = in.read();
|
|
return '\n';
|
|
|
|
case -1:
|
|
if (stack.size() > 0) {
|
|
in = (Reader)stack.pop();
|
|
ch = ((Integer)stack.pop()).intValue();
|
|
ln = ((Integer)stack.pop()).intValue();
|
|
return read();
|
|
}
|
|
return -1;
|
|
|
|
default:
|
|
int c = ch;
|
|
ch = in.read();
|
|
return c;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return the data as a stream.
|
|
*/
|
|
private Reader getEntityInputReader(Entity ent) throws IOException {
|
|
if ((ent.type & Entity.PUBLIC) != 0) {
|
|
// InputStream is = DTDBuilder.mapping.get(ent.getString()).openStream();
|
|
// return new InputStreamReader(is);
|
|
String path = DTDBuilder.mapping.get(ent.getString());
|
|
|
|
return new InputStreamReader(new FileInputStream(path));
|
|
}
|
|
if ((ent.type & Entity.SYSTEM) != 0) {
|
|
//InputStream is = new URL(DTDBuilder.mapping.base, ent.getString()).openStream();
|
|
String path = DTDBuilder.mapping.baseStr + ent.getString();
|
|
return new InputStreamReader(new FileInputStream(path));
|
|
}
|
|
return new CharArrayReader(ent.data);
|
|
}
|
|
|
|
}
|