feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,172 @@
/*
* Copyright (c) 1998, 2008, 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 javax.swing.text.html.parser;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
import java.io.*;
/**
* This class defines the attributes of an SGML element
* as described in a DTD using the ATTLIST construct.
* An AttributeList can be obtained from the Element
* class using the getAttributes() method.
* <p>
* It is actually an element in a linked list. Use the
* getNext() method repeatedly to enumerate all the attributes
* of an element.
*
* @see Element
* @author Arthur Van Hoff
*
*/
public final
class AttributeList implements DTDConstants, Serializable {
public String name;
public int type;
public Vector<?> values;
public int modifier;
public String value;
public AttributeList next;
AttributeList() {
}
/**
* Create an attribute list element.
*/
public AttributeList(String name) {
this.name = name;
}
/**
* Create an attribute list element.
*/
public AttributeList(String name, int type, int modifier, String value, Vector<?> values, AttributeList next) {
this.name = name;
this.type = type;
this.modifier = modifier;
this.value = value;
this.values = values;
this.next = next;
}
/**
* @return attribute name
*/
public String getName() {
return name;
}
/**
* @return attribute type
* @see DTDConstants
*/
public int getType() {
return type;
}
/**
* @return attribute modifier
* @see DTDConstants
*/
public int getModifier() {
return modifier;
}
/**
* @return possible attribute values
*/
public Enumeration<?> getValues() {
return (values != null) ? values.elements() : null;
}
/**
* @return default attribute value
*/
public String getValue() {
return value;
}
/**
* @return the next attribute in the list
*/
public AttributeList getNext() {
return next;
}
/**
* @return string representation
*/
public String toString() {
return name;
}
/**
* Create a hashtable of attribute types.
*/
static Hashtable<Object, Object> attributeTypes = new Hashtable<Object, Object>();
static void defineAttributeType(String nm, int val) {
Integer num = Integer.valueOf(val);
attributeTypes.put(nm, num);
attributeTypes.put(num, nm);
}
static {
defineAttributeType("CDATA", CDATA);
defineAttributeType("ENTITY", ENTITY);
defineAttributeType("ENTITIES", ENTITIES);
defineAttributeType("ID", ID);
defineAttributeType("IDREF", IDREF);
defineAttributeType("IDREFS", IDREFS);
defineAttributeType("NAME", NAME);
defineAttributeType("NAMES", NAMES);
defineAttributeType("NMTOKEN", NMTOKEN);
defineAttributeType("NMTOKENS", NMTOKENS);
defineAttributeType("NOTATION", NOTATION);
defineAttributeType("NUMBER", NUMBER);
defineAttributeType("NUMBERS", NUMBERS);
defineAttributeType("NUTOKEN", NUTOKEN);
defineAttributeType("NUTOKENS", NUTOKENS);
attributeTypes.put("fixed", Integer.valueOf(FIXED));
attributeTypes.put("required", Integer.valueOf(REQUIRED));
attributeTypes.put("current", Integer.valueOf(CURRENT));
attributeTypes.put("conref", Integer.valueOf(CONREF));
attributeTypes.put("implied", Integer.valueOf(IMPLIED));
}
public static int name2type(String nm) {
Integer i = (Integer)attributeTypes.get(nm);
return (i == null) ? CDATA : i.intValue();
}
public static String type2name(int tp) {
return (String)attributeTypes.get(Integer.valueOf(tp));
}
}

View File

@@ -0,0 +1,254 @@
/*
* Copyright (c) 1998, 2013, 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 javax.swing.text.html.parser;
import java.util.Vector;
import java.util.Enumeration;
import java.io.*;
/**
* A representation of a content model. A content model is
* basically a restricted BNF expression. It is restricted in
* the sense that it must be deterministic. This means that you
* don't have to represent it as a finite state automaton.<p>
* See Annex H on page 556 of the SGML handbook for more information.
*
* @author Arthur van Hoff
*
*/
public final class ContentModel implements Serializable {
/**
* Type. Either '*', '?', '+', ',', '|', '&amp;'.
*/
public int type;
/**
* The content. Either an Element or a ContentModel.
*/
public Object content;
/**
* The next content model (in a ',', '|' or '&amp;' expression).
*/
public ContentModel next;
public ContentModel() {
}
/**
* Create a content model for an element.
*/
public ContentModel(Element content) {
this(0, content, null);
}
/**
* Create a content model of a particular type.
*/
public ContentModel(int type, ContentModel content) {
this(type, content, null);
}
/**
* Create a content model of a particular type.
*/
public ContentModel(int type, Object content, ContentModel next) {
this.type = type;
this.content = content;
this.next = next;
}
/**
* Return true if the content model could
* match an empty input stream.
*/
public boolean empty() {
switch (type) {
case '*':
case '?':
return true;
case '+':
case '|':
for (ContentModel m = (ContentModel)content ; m != null ; m = m.next) {
if (m.empty()) {
return true;
}
}
return false;
case ',':
case '&':
for (ContentModel m = (ContentModel)content ; m != null ; m = m.next) {
if (!m.empty()) {
return false;
}
}
return true;
default:
return false;
}
}
/**
* Update elemVec with the list of elements that are
* part of the this contentModel.
*/
public void getElements(Vector<Element> elemVec) {
switch (type) {
case '*':
case '?':
case '+':
((ContentModel)content).getElements(elemVec);
break;
case ',':
case '|':
case '&':
for (ContentModel m=(ContentModel)content; m != null; m=m.next){
m.getElements(elemVec);
}
break;
default:
elemVec.addElement((Element)content);
}
}
private boolean valSet[];
private boolean val[];
// A cache used by first(). This cache was found to speed parsing
// by about 10% (based on measurements of the 4-12 code base after
// buffering was fixed).
/**
* Return true if the token could potentially be the
* first token in the input stream.
*/
public boolean first(Object token) {
switch (type) {
case '*':
case '?':
case '+':
return ((ContentModel)content).first(token);
case ',':
for (ContentModel m = (ContentModel)content ; m != null ; m = m.next) {
if (m.first(token)) {
return true;
}
if (!m.empty()) {
return false;
}
}
return false;
case '|':
case '&': {
Element e = (Element) token;
if (valSet == null || valSet.length <= Element.getMaxIndex()) {
valSet = new boolean[Element.getMaxIndex() + 1];
val = new boolean[valSet.length];
}
if (valSet[e.index]) {
return val[e.index];
}
for (ContentModel m = (ContentModel)content ; m != null ; m = m.next) {
if (m.first(token)) {
val[e.index] = true;
break;
}
}
valSet[e.index] = true;
return val[e.index];
}
default:
return (content == token);
// PENDING: refer to comment in ContentModelState
/*
if (content == token) {
return true;
}
Element e = (Element)content;
if (e.omitStart() && e.content != null) {
return e.content.first(token);
}
return false;
*/
}
}
/**
* Return the element that must be next.
*/
public Element first() {
switch (type) {
case '&':
case '|':
case '*':
case '?':
return null;
case '+':
case ',':
return ((ContentModel)content).first();
default:
return (Element)content;
}
}
/**
* Convert to a string.
*/
public String toString() {
switch (type) {
case '*':
return content + "*";
case '?':
return content + "?";
case '+':
return content + "+";
case ',':
case '|':
case '&':
char data[] = {' ', (char)type, ' '};
String str = "";
for (ContentModel m = (ContentModel)content ; m != null ; m = m.next) {
str = str + m;
if (m.next != null) {
str += new String(data);
}
}
return "(" + str + ")";
default:
return content.toString();
}
}
}

View File

@@ -0,0 +1,295 @@
/*
* Copyright (c) 1998, 2000, 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 javax.swing.text.html.parser;
/**
* A content model state. This is basically a list of pointers to
* the BNF expression representing the model (the ContentModel).
* Each element in a DTD has a content model which describes the
* elements that may occur inside, and the order in which they can
* occur.
* <p>
* Each time a token is reduced a new state is created.
* <p>
* See Annex H on page 556 of the SGML handbook for more information.
*
* @see Parser
* @see DTD
* @see Element
* @see ContentModel
* @author Arthur van Hoff
*/
class ContentModelState {
ContentModel model;
long value;
ContentModelState next;
/**
* Create a content model state for a content model.
*/
public ContentModelState(ContentModel model) {
this(model, null, 0);
}
/**
* Create a content model state for a content model given the
* remaining state that needs to be reduce.
*/
ContentModelState(Object content, ContentModelState next) {
this(content, next, 0);
}
/**
* Create a content model state for a content model given the
* remaining state that needs to be reduce.
*/
ContentModelState(Object content, ContentModelState next, long value) {
this.model = (ContentModel)content;
this.next = next;
this.value = value;
}
/**
* Return the content model that is relevant to the current state.
*/
public ContentModel getModel() {
ContentModel m = model;
for (int i = 0; i < value; i++) {
if (m.next != null) {
m = m.next;
} else {
return null;
}
}
return m;
}
/**
* Check if the state can be terminated. That is there are no more
* tokens required in the input stream.
* @return true if the model can terminate without further input
*/
public boolean terminate() {
switch (model.type) {
case '+':
if ((value == 0) && !(model).empty()) {
return false;
}
case '*':
case '?':
return (next == null) || next.terminate();
case '|':
for (ContentModel m = (ContentModel)model.content ; m != null ; m = m.next) {
if (m.empty()) {
return (next == null) || next.terminate();
}
}
return false;
case '&': {
ContentModel m = (ContentModel)model.content;
for (int i = 0 ; m != null ; i++, m = m.next) {
if ((value & (1L << i)) == 0) {
if (!m.empty()) {
return false;
}
}
}
return (next == null) || next.terminate();
}
case ',': {
ContentModel m = (ContentModel)model.content;
for (int i = 0 ; i < value ; i++, m = m.next);
for (; (m != null) && m.empty() ; m = m.next);
if (m != null) {
return false;
}
return (next == null) || next.terminate();
}
default:
return false;
}
}
/**
* Check if the state can be terminated. That is there are no more
* tokens required in the input stream.
* @return the only possible element that can occur next
*/
public Element first() {
switch (model.type) {
case '*':
case '?':
case '|':
case '&':
return null;
case '+':
return model.first();
case ',': {
ContentModel m = (ContentModel)model.content;
for (int i = 0 ; i < value ; i++, m = m.next);
return m.first();
}
default:
return model.first();
}
}
/**
* Advance this state to a new state. An exception is thrown if the
* token is illegal at this point in the content model.
* @return next state after reducing a token
*/
public ContentModelState advance(Object token) {
switch (model.type) {
case '+':
if (model.first(token)) {
return new ContentModelState(model.content,
new ContentModelState(model, next, value + 1)).advance(token);
}
if (value != 0) {
if (next != null) {
return next.advance(token);
} else {
return null;
}
}
break;
case '*':
if (model.first(token)) {
return new ContentModelState(model.content, this).advance(token);
}
if (next != null) {
return next.advance(token);
} else {
return null;
}
case '?':
if (model.first(token)) {
return new ContentModelState(model.content, next).advance(token);
}
if (next != null) {
return next.advance(token);
} else {
return null;
}
case '|':
for (ContentModel m = (ContentModel)model.content ; m != null ; m = m.next) {
if (m.first(token)) {
return new ContentModelState(m, next).advance(token);
}
}
break;
case ',': {
ContentModel m = (ContentModel)model.content;
for (int i = 0 ; i < value ; i++, m = m.next);
if (m.first(token) || m.empty()) {
if (m.next == null) {
return new ContentModelState(m, next).advance(token);
} else {
return new ContentModelState(m,
new ContentModelState(model, next, value + 1)).advance(token);
}
}
break;
}
case '&': {
ContentModel m = (ContentModel)model.content;
boolean complete = true;
for (int i = 0 ; m != null ; i++, m = m.next) {
if ((value & (1L << i)) == 0) {
if (m.first(token)) {
return new ContentModelState(m,
new ContentModelState(model, next, value | (1L << i))).advance(token);
}
if (!m.empty()) {
complete = false;
}
}
}
if (complete) {
if (next != null) {
return next.advance(token);
} else {
return null;
}
}
break;
}
default:
if (model.content == token) {
if (next == null && (token instanceof Element) &&
((Element)token).content != null) {
return new ContentModelState(((Element)token).content);
}
return next;
}
// PENDING: Currently we don't correctly deal with optional start
// tags. This can most notably be seen with the 4.01 spec where
// TBODY's start and end tags are optional.
// Uncommenting this and the PENDING in ContentModel will
// correctly skip the omit tags, but the delegate is not notified.
// Some additional API needs to be added to track skipped tags,
// and this can then be added back.
/*
if ((model.content instanceof Element)) {
Element e = (Element)model.content;
if (e.omitStart() && e.content != null) {
return new ContentModelState(e.content, next).advance(
token);
}
}
*/
}
// We used to throw this exception at this point. However, it
// was determined that throwing this exception was more expensive
// than returning null, and we could not justify to ourselves why
// it was necessary to throw an exception, rather than simply
// returning null. I'm leaving it in a commented out state so
// that it can be easily restored if the situation ever arises.
//
// throw new IllegalArgumentException("invalid token: " + token);
return null;
}
}

View File

@@ -0,0 +1,466 @@
/*
* Copyright (c) 1998, 2010, 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 javax.swing.text.html.parser;
import sun.awt.AppContext;
import java.io.PrintStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.util.Hashtable;
import java.util.Vector;
import java.util.BitSet;
import java.util.StringTokenizer;
import java.util.Enumeration;
import java.util.Properties;
import java.net.URL;
/**
* The representation of an SGML DTD. DTD describes a document
* syntax and is used in parsing of HTML documents. It contains
* a list of elements and their attributes as well as a list of
* entities defined in the DTD.
*
* @see Element
* @see AttributeList
* @see ContentModel
* @see Parser
* @author Arthur van Hoff
*/
public
class DTD implements DTDConstants {
public String name;
public Vector<Element> elements = new Vector<Element>();
public Hashtable<String,Element> elementHash
= new Hashtable<String,Element>();
public Hashtable<Object,Entity> entityHash
= new Hashtable<Object,Entity>();
public final Element pcdata = getElement("#pcdata");
public final Element html = getElement("html");
public final Element meta = getElement("meta");
public final Element base = getElement("base");
public final Element isindex = getElement("isindex");
public final Element head = getElement("head");
public final Element body = getElement("body");
public final Element applet = getElement("applet");
public final Element param = getElement("param");
public final Element p = getElement("p");
public final Element title = getElement("title");
final Element style = getElement("style");
final Element link = getElement("link");
final Element script = getElement("script");
public static final int FILE_VERSION = 1;
/**
* Creates a new DTD with the specified name.
* @param name the name, as a <code>String</code> of the new DTD
*/
protected DTD(String name) {
this.name = name;
defEntity("#RE", GENERAL, '\r');
defEntity("#RS", GENERAL, '\n');
defEntity("#SPACE", GENERAL, ' ');
defineElement("unknown", EMPTY, false, true, null, null, null, null);
}
/**
* Gets the name of the DTD.
* @return the name of the DTD
*/
public String getName() {
return name;
}
/**
* Gets an entity by name.
* @return the <code>Entity</code> corresponding to the
* <code>name</code> <code>String</code>
*/
public Entity getEntity(String name) {
return entityHash.get(name);
}
/**
* Gets a character entity.
* @return the <code>Entity</code> corresponding to the
* <code>ch</code> character
*/
public Entity getEntity(int ch) {
return entityHash.get(Integer.valueOf(ch));
}
/**
* Returns <code>true</code> if the element is part of the DTD,
* otherwise returns <code>false</code>.
*
* @param name the requested <code>String</code>
* @return <code>true</code> if <code>name</code> exists as
* part of the DTD, otherwise returns <code>false</code>
*/
boolean elementExists(String name) {
return !"unknown".equals(name) && (elementHash.get(name) != null);
}
/**
* Gets an element by name. A new element is
* created if the element doesn't exist.
*
* @param name the requested <code>String</code>
* @return the <code>Element</code> corresponding to
* <code>name</code>, which may be newly created
*/
public Element getElement(String name) {
Element e = elementHash.get(name);
if (e == null) {
e = new Element(name, elements.size());
elements.addElement(e);
elementHash.put(name, e);
}
return e;
}
/**
* Gets an element by index.
*
* @param index the requested index
* @return the <code>Element</code> corresponding to
* <code>index</code>
*/
public Element getElement(int index) {
return elements.elementAt(index);
}
/**
* Defines an entity. If the <code>Entity</code> specified
* by <code>name</code>, <code>type</code>, and <code>data</code>
* exists, it is returned; otherwise a new <code>Entity</code>
* is created and is returned.
*
* @param name the name of the <code>Entity</code> as a <code>String</code>
* @param type the type of the <code>Entity</code>
* @param data the <code>Entity</code>'s data
* @return the <code>Entity</code> requested or a new <code>Entity</code>
* if not found
*/
public Entity defineEntity(String name, int type, char data[]) {
Entity ent = entityHash.get(name);
if (ent == null) {
ent = new Entity(name, type, data);
entityHash.put(name, ent);
if (((type & GENERAL) != 0) && (data.length == 1)) {
switch (type & ~GENERAL) {
case CDATA:
case SDATA:
entityHash.put(Integer.valueOf(data[0]), ent);
break;
}
}
}
return ent;
}
/**
* Returns the <code>Element</code> which matches the
* specified parameters. If one doesn't exist, a new
* one is created and returned.
*
* @param name the name of the <code>Element</code>
* @param type the type of the <code>Element</code>
* @param omitStart <code>true</code> if start should be omitted
* @param omitEnd <code>true</code> if end should be omitted
* @param content the <code>ContentModel</code>
* @param atts the <code>AttributeList</code> specifying the
* <code>Element</code>
* @return the <code>Element</code> specified
*/
public Element defineElement(String name, int type,
boolean omitStart, boolean omitEnd, ContentModel content,
BitSet exclusions, BitSet inclusions, AttributeList atts) {
Element e = getElement(name);
e.type = type;
e.oStart = omitStart;
e.oEnd = omitEnd;
e.content = content;
e.exclusions = exclusions;
e.inclusions = inclusions;
e.atts = atts;
return e;
}
/**
* Defines attributes for an {@code Element}.
*
* @param name the name of the <code>Element</code>
* @param atts the <code>AttributeList</code> specifying the
* <code>Element</code>
*/
public void defineAttributes(String name, AttributeList atts) {
Element e = getElement(name);
e.atts = atts;
}
/**
* Creates and returns a character <code>Entity</code>.
* @param name the entity's name
* @return the new character <code>Entity</code>
*/
public Entity defEntity(String name, int type, int ch) {
char data[] = {(char)ch};
return defineEntity(name, type, data);
}
/**
* Creates and returns an <code>Entity</code>.
* @param name the entity's name
* @return the new <code>Entity</code>
*/
protected Entity defEntity(String name, int type, String str) {
int len = str.length();
char data[] = new char[len];
str.getChars(0, len, data, 0);
return defineEntity(name, type, data);
}
/**
* Creates and returns an <code>Element</code>.
* @param name the element's name
* @return the new <code>Element</code>
*/
protected Element defElement(String name, int type,
boolean omitStart, boolean omitEnd, ContentModel content,
String[] exclusions, String[] inclusions, AttributeList atts) {
BitSet excl = null;
if (exclusions != null && exclusions.length > 0) {
excl = new BitSet();
for (String str : exclusions) {
if (str.length() > 0) {
excl.set(getElement(str).getIndex());
}
}
}
BitSet incl = null;
if (inclusions != null && inclusions.length > 0) {
incl = new BitSet();
for (String str : inclusions) {
if (str.length() > 0) {
incl.set(getElement(str).getIndex());
}
}
}
return defineElement(name, type, omitStart, omitEnd, content, excl, incl, atts);
}
/**
* Creates and returns an <code>AttributeList</code>.
* @param name the attribute list's name
* @return the new <code>AttributeList</code>
*/
protected AttributeList defAttributeList(String name, int type, int modifier, String value, String values, AttributeList atts) {
Vector<String> vals = null;
if (values != null) {
vals = new Vector<String>();
for (StringTokenizer s = new StringTokenizer(values, "|") ; s.hasMoreTokens() ;) {
String str = s.nextToken();
if (str.length() > 0) {
vals.addElement(str);
}
}
}
return new AttributeList(name, type, modifier, value, vals, atts);
}
/**
* Creates and returns a new content model.
* @param type the type of the new content model
* @return the new <code>ContentModel</code>
*/
protected ContentModel defContentModel(int type, Object obj, ContentModel next) {
return new ContentModel(type, obj, next);
}
/**
* Returns a string representation of this DTD.
* @return the string representation of this DTD
*/
public String toString() {
return name;
}
/**
* The hashtable key of DTDs in AppContext.
*/
private static final Object DTD_HASH_KEY = new Object();
public static void putDTDHash(String name, DTD dtd) {
getDtdHash().put(name, dtd);
}
/**
* Returns a DTD with the specified <code>name</code>. If
* a DTD with that name doesn't exist, one is created
* and returned. Any uppercase characters in the name
* are converted to lowercase.
*
* @param name the name of the DTD
* @return the DTD which corresponds to <code>name</code>
*/
public static DTD getDTD(String name) throws IOException {
name = name.toLowerCase();
DTD dtd = getDtdHash().get(name);
if (dtd == null)
dtd = new DTD(name);
return dtd;
}
private static Hashtable<String, DTD> getDtdHash() {
AppContext appContext = AppContext.getAppContext();
Hashtable<String, DTD> result = (Hashtable<String, DTD>) appContext.get(DTD_HASH_KEY);
if (result == null) {
result = new Hashtable<String, DTD>();
appContext.put(DTD_HASH_KEY, result);
}
return result;
}
/**
* Recreates a DTD from an archived format.
* @param in the <code>DataInputStream</code> to read from
*/
public void read(DataInputStream in) throws IOException {
if (in.readInt() != FILE_VERSION) {
}
//
// Read the list of names
//
String[] names = new String[in.readShort()];
for (int i = 0; i < names.length; i++) {
names[i] = in.readUTF();
}
//
// Read the entities
//
int num = in.readShort();
for (int i = 0; i < num; i++) {
short nameId = in.readShort();
int type = in.readByte();
String name = in.readUTF();
defEntity(names[nameId], type | GENERAL, name);
}
// Read the elements
//
num = in.readShort();
for (int i = 0; i < num; i++) {
short nameId = in.readShort();
int type = in.readByte();
byte flags = in.readByte();
ContentModel m = readContentModel(in, names);
String[] exclusions = readNameArray(in, names);
String[] inclusions = readNameArray(in, names);
AttributeList atts = readAttributeList(in, names);
defElement(names[nameId], type,
((flags & 0x01) != 0), ((flags & 0x02) != 0),
m, exclusions, inclusions, atts);
}
}
private ContentModel readContentModel(DataInputStream in, String[] names)
throws IOException {
byte flag = in.readByte();
switch(flag) {
case 0: // null
return null;
case 1: { // content_c
int type = in.readByte();
ContentModel m = readContentModel(in, names);
ContentModel next = readContentModel(in, names);
return defContentModel(type, m, next);
}
case 2: { // content_e
int type = in.readByte();
Element el = getElement(names[in.readShort()]);
ContentModel next = readContentModel(in, names);
return defContentModel(type, el, next);
}
default:
throw new IOException("bad bdtd");
}
}
private String[] readNameArray(DataInputStream in, String[] names)
throws IOException {
int num = in.readShort();
if (num == 0) {
return null;
}
String[] result = new String[num];
for (int i = 0; i < num; i++) {
result[i] = names[in.readShort()];
}
return result;
}
private AttributeList readAttributeList(DataInputStream in, String[] names)
throws IOException {
AttributeList result = null;
for (int num = in.readByte(); num > 0; --num) {
short nameId = in.readShort();
int type = in.readByte();
int modifier = in.readByte();
short valueId = in.readShort();
String value = (valueId == -1) ? null : names[valueId];
Vector<String> values = null;
short numValues = in.readShort();
if (numValues > 0) {
values = new Vector<String>(numValues);
for (int i = 0; i < numValues; i++) {
values.addElement(names[in.readShort()]);
}
}
result = new AttributeList(names[nameId], type, modifier, value,
values, result);
// We reverse the order of the linked list by doing this, but
// that order isn't important.
}
return result;
}
}

View File

@@ -0,0 +1,82 @@
/*
* Copyright (c) 1998, 1999, 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 javax.swing.text.html.parser;
/**
* SGML constants used in a DTD. The names of the
* constants correspond the the equivalent SGML constructs
* as described in "The SGML Handbook" by Charles F. Goldfarb.
*
* @see DTD
* @see Element
* @author Arthur van Hoff
*/
public
interface DTDConstants {
// Attribute value types
int CDATA = 1;
int ENTITY = 2;
int ENTITIES = 3;
int ID = 4;
int IDREF = 5;
int IDREFS = 6;
int NAME = 7;
int NAMES = 8;
int NMTOKEN = 9;
int NMTOKENS = 10;
int NOTATION = 11;
int NUMBER = 12;
int NUMBERS = 13;
int NUTOKEN = 14;
int NUTOKENS = 15;
// Content model types
int RCDATA = 16;
int EMPTY = 17;
int MODEL = 18;
int ANY = 19;
// Attribute value modifiers
int FIXED = 1;
int REQUIRED = 2;
int CURRENT = 3;
int CONREF = 4;
int IMPLIED = 5;
// Entity types
int PUBLIC = 10;
int SDATA = 11;
int PI = 12;
int STARTTAG = 13;
int ENDTAG = 14;
int MS = 15;
int MD = 16;
int SYSTEM = 17;
int GENERAL = 1<<16;
int DEFAULT = 1<<17;
int PARAMETER = 1<<18;
}

View File

@@ -0,0 +1,281 @@
/*
* Copyright (c) 1998, 2013, 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 javax.swing.text.html.parser;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.HTML;
import javax.swing.text.ChangedCharSetException;
import java.util.*;
import java.io.*;
import java.net.*;
/**
* A Parser for HTML Documents (actually, you can specify a DTD, but
* you should really only use this class with the html dtd in swing).
* Reads an InputStream of HTML and
* invokes the appropriate methods in the ParserCallback class. This
* is the default parser used by HTMLEditorKit to parse HTML url's.
* <p>This will message the callback for all valid tags, as well as
* tags that are implied but not explicitly specified. For example, the
* html string (&lt;p&gt;blah) only has a p tag defined. The callback
* will see the following methods:
* <ol><li><i>handleStartTag(html, ...)</i></li>
* <li><i>handleStartTag(head, ...)</i></li>
* <li><i>handleEndTag(head)</i></li>
* <li><i>handleStartTag(body, ...)</i></li>
* <li><i>handleStartTag(p, ...)</i></li>
* <li><i>handleText(...)</i></li>
* <li><i>handleEndTag(p)</i></li>
* <li><i>handleEndTag(body)</i></li>
* <li><i>handleEndTag(html)</i></li>
* </ol>
* The items in <i>italic</i> are implied, that is, although they were not
* explicitly specified, to be correct html they should have been present
* (head isn't necessary, but it is still generated). For tags that
* are implied, the AttributeSet argument will have a value of
* <code>Boolean.TRUE</code> for the key
* <code>HTMLEditorKit.ParserCallback.IMPLIED</code>.
* <p>HTML.Attributes defines a type safe enumeration of html attributes.
* If an attribute key of a tag is defined in HTML.Attribute, the
* HTML.Attribute will be used as the key, otherwise a String will be used.
* For example &lt;p foo=bar class=neat&gt; has two attributes. foo is
* not defined in HTML.Attribute, where as class is, therefore the
* AttributeSet will have two values in it, HTML.Attribute.CLASS with
* a String value of 'neat' and the String key 'foo' with a String value of
* 'bar'.
* <p>The position argument will indicate the start of the tag, comment
* or text. Similar to arrays, the first character in the stream has a
* position of 0. For tags that are
* implied the position will indicate
* the location of the next encountered tag. In the first example,
* the implied start body and html tags will have the same position as the
* p tag, and the implied end p, html and body tags will all have the same
* position.
* <p>As html skips whitespace the position for text will be the position
* of the first valid character, eg in the string '\n\n\nblah'
* the text 'blah' will have a position of 3, the newlines are skipped.
* <p>
* For attributes that do not have a value, eg in the html
* string <code>&lt;foo blah&gt;</code> the attribute <code>blah</code>
* does not have a value, there are two possible values that will be
* placed in the AttributeSet's value:
* <ul>
* <li>If the DTD does not contain an definition for the element, or the
* definition does not have an explicit value then the value in the
* AttributeSet will be <code>HTML.NULL_ATTRIBUTE_VALUE</code>.
* <li>If the DTD contains an explicit value, as in:
* <code>&lt;!ATTLIST OPTION selected (selected) #IMPLIED&gt;</code>
* this value from the dtd (in this case selected) will be used.
* </ul>
* <p>
* Once the stream has been parsed, the callback is notified of the most
* likely end of line string. The end of line string will be one of
* \n, \r or \r\n, which ever is encountered the most in parsing the
* stream.
*
* @author Sunita Mani
*/
public class DocumentParser extends javax.swing.text.html.parser.Parser {
private int inbody;
private int intitle;
private int inhead;
private int instyle;
private int inscript;
private boolean seentitle;
private HTMLEditorKit.ParserCallback callback = null;
private boolean ignoreCharSet = false;
private static final boolean debugFlag = false;
public DocumentParser(DTD dtd) {
super(dtd);
}
public void parse(Reader in, HTMLEditorKit.ParserCallback callback, boolean ignoreCharSet) throws IOException {
this.ignoreCharSet = ignoreCharSet;
this.callback = callback;
parse(in);
// end of line
callback.handleEndOfLineString(getEndOfLineString());
}
/**
* Handle Start Tag.
*/
protected void handleStartTag(TagElement tag) {
Element elem = tag.getElement();
if (elem == dtd.body) {
inbody++;
} else if (elem == dtd.html) {
} else if (elem == dtd.head) {
inhead++;
} else if (elem == dtd.title) {
intitle++;
} else if (elem == dtd.style) {
instyle++;
} else if (elem == dtd.script) {
inscript++;
}
if (debugFlag) {
if (tag.fictional()) {
debug("Start Tag: " + tag.getHTMLTag() + " pos: " + getCurrentPos());
} else {
debug("Start Tag: " + tag.getHTMLTag() + " attributes: " +
getAttributes() + " pos: " + getCurrentPos());
}
}
if (tag.fictional()) {
SimpleAttributeSet attrs = new SimpleAttributeSet();
attrs.addAttribute(HTMLEditorKit.ParserCallback.IMPLIED,
Boolean.TRUE);
callback.handleStartTag(tag.getHTMLTag(), attrs,
getBlockStartPosition());
} else {
callback.handleStartTag(tag.getHTMLTag(), getAttributes(),
getBlockStartPosition());
flushAttributes();
}
}
protected void handleComment(char text[]) {
if (debugFlag) {
debug("comment: ->" + new String(text) + "<-"
+ " pos: " + getCurrentPos());
}
callback.handleComment(text, getBlockStartPosition());
}
/**
* Handle Empty Tag.
*/
protected void handleEmptyTag(TagElement tag) throws ChangedCharSetException {
Element elem = tag.getElement();
if (elem == dtd.meta && !ignoreCharSet) {
SimpleAttributeSet atts = getAttributes();
if (atts != null) {
String content = (String)atts.getAttribute(HTML.Attribute.CONTENT);
if (content != null) {
if ("content-type".equalsIgnoreCase((String)atts.getAttribute(HTML.Attribute.HTTPEQUIV))) {
if (!content.equalsIgnoreCase("text/html") &&
!content.equalsIgnoreCase("text/plain")) {
throw new ChangedCharSetException(content, false);
}
} else if ("charset" .equalsIgnoreCase((String)atts.getAttribute(HTML.Attribute.HTTPEQUIV))) {
throw new ChangedCharSetException(content, true);
}
}
}
}
if (inbody != 0 || elem == dtd.meta || elem == dtd.base || elem == dtd.isindex || elem == dtd.style || elem == dtd.link) {
if (debugFlag) {
if (tag.fictional()) {
debug("Empty Tag: " + tag.getHTMLTag() + " pos: " + getCurrentPos());
} else {
debug("Empty Tag: " + tag.getHTMLTag() + " attributes: "
+ getAttributes() + " pos: " + getCurrentPos());
}
}
if (tag.fictional()) {
SimpleAttributeSet attrs = new SimpleAttributeSet();
attrs.addAttribute(HTMLEditorKit.ParserCallback.IMPLIED,
Boolean.TRUE);
callback.handleSimpleTag(tag.getHTMLTag(), attrs,
getBlockStartPosition());
} else {
callback.handleSimpleTag(tag.getHTMLTag(), getAttributes(),
getBlockStartPosition());
flushAttributes();
}
}
}
/**
* Handle End Tag.
*/
protected void handleEndTag(TagElement tag) {
Element elem = tag.getElement();
if (elem == dtd.body) {
inbody--;
} else if (elem == dtd.title) {
intitle--;
seentitle = true;
} else if (elem == dtd.head) {
inhead--;
} else if (elem == dtd.style) {
instyle--;
} else if (elem == dtd.script) {
inscript--;
}
if (debugFlag) {
debug("End Tag: " + tag.getHTMLTag() + " pos: " + getCurrentPos());
}
callback.handleEndTag(tag.getHTMLTag(), getBlockStartPosition());
}
/**
* Handle Text.
*/
protected void handleText(char data[]) {
if (data != null) {
if (inscript != 0) {
callback.handleComment(data, getBlockStartPosition());
return;
}
if (inbody != 0 || ((instyle != 0) ||
((intitle != 0) && !seentitle))) {
if (debugFlag) {
debug("text: ->" + new String(data) + "<-" + " pos: " + getCurrentPos());
}
callback.handleText(data, getBlockStartPosition());
}
}
}
/*
* Error handling.
*/
protected void handleError(int ln, String errorMsg) {
if (debugFlag) {
debug("Error: ->" + errorMsg + "<-" + " pos: " + getCurrentPos());
}
/* PENDING: need to improve the error string. */
callback.handleError(errorMsg, getCurrentPos());
}
/*
* debug messages
*/
private void debug(String msg) {
System.out.println(msg);
}
}

View File

@@ -0,0 +1,185 @@
/*
* Copyright (c) 1998, 2013, 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 javax.swing.text.html.parser;
import java.util.Hashtable;
import java.util.BitSet;
import java.io.*;
import sun.awt.AppContext;
/**
* An element as described in a DTD using the ELEMENT construct.
* This is essential the description of a tag. It describes the
* type, content model, attributes, attribute types etc. It is used
* to correctly parse a document by the Parser.
*
* @see DTD
* @see AttributeList
* @author Arthur van Hoff
*/
public final
class Element implements DTDConstants, Serializable {
public int index;
public String name;
public boolean oStart;
public boolean oEnd;
public BitSet inclusions;
public BitSet exclusions;
public int type = ANY;
public ContentModel content;
public AttributeList atts;
/**
* A field to store user data. Mostly used to store
* style sheets.
*/
public Object data;
Element() {
}
/**
* Create a new element.
*/
Element(String name, int index) {
this.name = name;
this.index = index;
if (index > getMaxIndex()) {
AppContext.getAppContext().put(MAX_INDEX_KEY, index);
}
}
private static final Object MAX_INDEX_KEY = new Object();
static int getMaxIndex() {
Integer value = (Integer) AppContext.getAppContext().get(MAX_INDEX_KEY);
return (value != null)
? value.intValue()
: 0;
}
/**
* Get the name of the element.
*/
public String getName() {
return name;
}
/**
* Return true if the start tag can be omitted.
*/
public boolean omitStart() {
return oStart;
}
/**
* Return true if the end tag can be omitted.
*/
public boolean omitEnd() {
return oEnd;
}
/**
* Get type.
*/
public int getType() {
return type;
}
/**
* Get content model
*/
public ContentModel getContent() {
return content;
}
/**
* Get the attributes.
*/
public AttributeList getAttributes() {
return atts;
}
/**
* Get index.
*/
public int getIndex() {
return index;
}
/**
* Check if empty
*/
public boolean isEmpty() {
return type == EMPTY;
}
/**
* Convert to a string.
*/
public String toString() {
return name;
}
/**
* Get an attribute by name.
*/
public AttributeList getAttribute(String name) {
for (AttributeList a = atts ; a != null ; a = a.next) {
if (a.name.equals(name)) {
return a;
}
}
return null;
}
/**
* Get an attribute by value.
*/
public AttributeList getAttributeByValue(String name) {
for (AttributeList a = atts ; a != null ; a = a.next) {
if ((a.values != null) && a.values.contains(name)) {
return a;
}
}
return null;
}
static Hashtable<String, Integer> contentTypes = new Hashtable<String, Integer>();
static {
contentTypes.put("CDATA", Integer.valueOf(CDATA));
contentTypes.put("RCDATA", Integer.valueOf(RCDATA));
contentTypes.put("EMPTY", Integer.valueOf(EMPTY));
contentTypes.put("ANY", Integer.valueOf(ANY));
}
public static int name2type(String nm) {
Integer val = contentTypes.get(nm);
return (val != null) ? val.intValue() : 0;
}
}

View File

@@ -0,0 +1,139 @@
/*
* Copyright (c) 1998, 2008, 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 javax.swing.text.html.parser;
import java.util.Hashtable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.CharArrayReader;
import java.net.URL;
/**
* An entity is described in a DTD using the ENTITY construct.
* It defines the type and value of the the entity.
*
* @see DTD
* @author Arthur van Hoff
*/
public final
class Entity implements DTDConstants {
public String name;
public int type;
public char data[];
/**
* Creates an entity.
* @param name the name of the entity
* @param type the type of the entity
* @param data the char array of data
*/
public Entity(String name, int type, char data[]) {
this.name = name;
this.type = type;
this.data = data;
}
/**
* Gets the name of the entity.
* @return the name of the entity, as a <code>String</code>
*/
public String getName() {
return name;
}
/**
* Gets the type of the entity.
* @return the type of the entity
*/
public int getType() {
return type & 0xFFFF;
}
/**
* Returns <code>true</code> if it is a parameter entity.
* @return <code>true</code> if it is a parameter entity
*/
public boolean isParameter() {
return (type & PARAMETER) != 0;
}
/**
* Returns <code>true</code> if it is a general entity.
* @return <code>true</code> if it is a general entity
*/
public boolean isGeneral() {
return (type & GENERAL) != 0;
}
/**
* Returns the <code>data</code>.
* @return the <code>data</code>
*/
public char getData()[] {
return data;
}
/**
* Returns the data as a <code>String</code>.
* @return the data as a <code>String</code>
*/
public String getString() {
return new String(data, 0, data.length);
}
static Hashtable<String, Integer> entityTypes = new Hashtable<String, Integer>();
static {
entityTypes.put("PUBLIC", Integer.valueOf(PUBLIC));
entityTypes.put("CDATA", Integer.valueOf(CDATA));
entityTypes.put("SDATA", Integer.valueOf(SDATA));
entityTypes.put("PI", Integer.valueOf(PI));
entityTypes.put("STARTTAG", Integer.valueOf(STARTTAG));
entityTypes.put("ENDTAG", Integer.valueOf(ENDTAG));
entityTypes.put("MS", Integer.valueOf(MS));
entityTypes.put("MD", Integer.valueOf(MD));
entityTypes.put("SYSTEM", Integer.valueOf(SYSTEM));
}
/**
* Converts <code>nm</code> string to the corresponding
* entity type. If the string does not have a corresponding
* entity type, returns the type corresponding to "CDATA".
* Valid entity types are: "PUBLIC", "CDATA", "SDATA", "PI",
* "STARTTAG", "ENDTAG", "MS", "MD", "SYSTEM".
*
* @param nm the string to be converted
* @return the corresponding entity type, or the type corresponding
* to "CDATA", if none exists
*/
public static int name2type(String nm) {
Integer i = entityTypes.get(nm);
return (i == null) ? CDATA : i.intValue();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,129 @@
/*
* Copyright (c) 1998, 2011, 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 javax.swing.text.html.parser;
import sun.awt.AppContext;
import javax.swing.text.html.HTMLEditorKit;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.DataInputStream;
import java.io.ObjectInputStream;
import java.io.Reader;
import java.io.Serializable;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
* Responsible for starting up a new DocumentParser
* each time its parse method is invoked. Stores a
* reference to the dtd.
*
* @author Sunita Mani
*/
public class ParserDelegator extends HTMLEditorKit.Parser implements Serializable {
private static final Object DTD_KEY = new Object();
protected static void setDefaultDTD() {
getDefaultDTD();
}
private static synchronized DTD getDefaultDTD() {
AppContext appContext = AppContext.getAppContext();
DTD dtd = (DTD) appContext.get(DTD_KEY);
if (dtd == null) {
DTD _dtd = null;
// (PENDING) Hate having to hard code!
String nm = "html32";
try {
_dtd = DTD.getDTD(nm);
} catch (IOException e) {
// (PENDING) UGLY!
System.out.println("Throw an exception: could not get default dtd: " + nm);
}
dtd = createDTD(_dtd, nm);
appContext.put(DTD_KEY, dtd);
}
return dtd;
}
protected static DTD createDTD(DTD dtd, String name) {
InputStream in = null;
boolean debug = true;
try {
String path = name + ".bdtd";
in = getResourceAsStream(path);
if (in != null) {
dtd.read(new DataInputStream(new BufferedInputStream(in)));
dtd.putDTDHash(name, dtd);
}
} catch (Exception e) {
System.out.println(e);
}
return dtd;
}
public ParserDelegator() {
setDefaultDTD();
}
public void parse(Reader r, HTMLEditorKit.ParserCallback cb, boolean ignoreCharSet) throws IOException {
new DocumentParser(getDefaultDTD()).parse(r, cb, ignoreCharSet);
}
/**
* Fetch a resource relative to the ParserDelegator classfile.
* If this is called on 1.2 the loading will occur under the
* protection of a doPrivileged call to allow the ParserDelegator
* to function when used in an applet.
*
* @param name the name of the resource, relative to the
* ParserDelegator class.
* @returns a stream representing the resource
*/
static InputStream getResourceAsStream(final String name) {
return AccessController.doPrivileged(
new PrivilegedAction<InputStream>() {
public InputStream run() {
return ParserDelegator.class.getResourceAsStream(name);
}
});
}
private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException {
s.defaultReadObject();
setDefaultDTD();
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (c) 1998, 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 javax.swing.text.html.parser;
import javax.swing.text.html.HTML;
/**
* A generic HTML TagElement class. The methods define how white
* space is interpreted around the tag.
*
* @author Sunita Mani
*/
public class TagElement {
Element elem;
HTML.Tag htmlTag;
boolean insertedByErrorRecovery;
public TagElement ( Element elem ) {
this(elem, false);
}
public TagElement (Element elem, boolean fictional) {
this.elem = elem;
htmlTag = HTML.getTag(elem.getName());
if (htmlTag == null) {
htmlTag = new HTML.UnknownTag(elem.getName());
}
insertedByErrorRecovery = fictional;
}
public boolean breaksFlow() {
return htmlTag.breaksFlow();
}
public boolean isPreformatted() {
return htmlTag.isPreformatted();
}
public Element getElement() {
return elem;
}
public HTML.Tag getHTMLTag() {
return htmlTag;
}
public boolean fictional() {
return insertedByErrorRecovery;
}
}

View File

@@ -0,0 +1,204 @@
/*
* Copyright (c) 1998, 2008, 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 javax.swing.text.html.parser;
import java.util.BitSet;
import java.util.Vector;
import java.io.*;
/**
* A stack of tags. Used while parsing an HTML document.
* It, together with the ContentModelStates, defines the
* complete state of the parser while reading a document.
* When a start tag is encountered an element is pushed onto
* the stack, when an end tag is enountered an element is popped
* of the stack.
*
* @see Parser
* @see DTD
* @see ContentModelState
* @author Arthur van Hoff
*/
final
class TagStack implements DTDConstants {
TagElement tag;
Element elem;
ContentModelState state;
TagStack next;
BitSet inclusions;
BitSet exclusions;
boolean net;
boolean pre;
/**
* Construct a stack element.
*/
TagStack(TagElement tag, TagStack next) {
this.tag = tag;
this.elem = tag.getElement();
this.next = next;
Element elem = tag.getElement();
if (elem.getContent() != null) {
this.state = new ContentModelState(elem.getContent());
}
if (next != null) {
inclusions = next.inclusions;
exclusions = next.exclusions;
pre = next.pre;
}
if (tag.isPreformatted()) {
pre = true;
}
if (elem.inclusions != null) {
if (inclusions != null) {
inclusions = (BitSet)inclusions.clone();
inclusions.or(elem.inclusions);
} else {
inclusions = elem.inclusions;
}
}
if (elem.exclusions != null) {
if (exclusions != null) {
exclusions = (BitSet)exclusions.clone();
exclusions.or(elem.exclusions);
} else {
exclusions = elem.exclusions;
}
}
}
/**
* Return the element that must come next in the
* input stream.
*/
public Element first() {
return (state != null) ? state.first() : null;
}
/**
* Return the ContentModel that must be satisfied by
* what comes next in the input stream.
*/
public ContentModel contentModel() {
if (state == null) {
return null;
} else {
return state.getModel();
}
}
/**
* Return true if the element that is contained at
* the index specified by the parameter is part of
* the exclusions specified in the DTD for the element
* currently on the TagStack.
*/
boolean excluded(int elemIndex) {
return (exclusions != null) && exclusions.get(elem.getIndex());
}
/**
* Advance the state by reducing the given element.
* Returns false if the element is not legal and the
* state is not advanced.
*/
boolean advance(Element elem) {
if ((exclusions != null) && exclusions.get(elem.getIndex())) {
return false;
}
if (state != null) {
ContentModelState newState = state.advance(elem);
if (newState != null) {
state = newState;
return true;
}
} else if (this.elem.getType() == ANY) {
return true;
}
return (inclusions != null) && inclusions.get(elem.getIndex());
}
/**
* Return true if the current state can be terminated.
*/
boolean terminate() {
return (state == null) || state.terminate();
}
/**
* Convert to a string.
*/
public String toString() {
return (next == null) ?
"<" + tag.getElement().getName() + ">" :
next + " <" + tag.getElement().getName() + ">";
}
}
class NPrintWriter extends PrintWriter {
private int numLines = 5;
private int numPrinted = 0;
public NPrintWriter (int numberOfLines) {
super(System.out);
numLines = numberOfLines;
}
public void println(char[] array) {
if (numPrinted >= numLines) {
return;
}
char[] partialArray = null;
for (int i = 0; i < array.length; i++) {
if (array[i] == '\n') {
numPrinted++;
}
if (numPrinted == numLines) {
System.arraycopy(array, 0, partialArray, 0, i);
}
}
if (partialArray != null) {
super.print(partialArray);
}
if (numPrinted == numLines) {
return;
}
super.println(array);
numPrinted++;
}
}