feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2012, 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 com.sun.xml.internal.stream.buffer.sax;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
public class DefaultWithLexicalHandler extends DefaultHandler implements LexicalHandler {
|
||||
|
||||
public void comment(char[] ch, int start, int length) throws SAXException { }
|
||||
|
||||
public void startDTD(String name, String publicId, String systemId) throws SAXException { }
|
||||
|
||||
public void endDTD() throws SAXException { }
|
||||
|
||||
public void startEntity(String name) throws SAXException { }
|
||||
|
||||
public void endEntity(String name) throws SAXException { }
|
||||
|
||||
public void startCDATA() throws SAXException { }
|
||||
|
||||
public void endCDATA() throws SAXException { }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2012, 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 com.sun.xml.internal.stream.buffer.sax;
|
||||
|
||||
public class Features {
|
||||
public static final String NAMESPACES_FEATURE =
|
||||
"http://xml.org/sax/features/namespaces";
|
||||
public static final String NAMESPACE_PREFIXES_FEATURE =
|
||||
"http://xml.org/sax/features/namespace-prefixes";
|
||||
public static final String EXTERNAL_GENERAL_ENTITIES =
|
||||
"http://xml.org/sax/features/external-general-entities";
|
||||
public static final String EXTERNAL_PARAMETER_ENTITIES =
|
||||
"http://xml.org/sax/features/external-parameter-entities";
|
||||
public static final String STRING_INTERNING_FEATURE =
|
||||
"http://xml.org/sax/features/string-interning";
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2012, 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 com.sun.xml.internal.stream.buffer.sax;
|
||||
|
||||
public class Properties {
|
||||
public static final String LEXICAL_HANDLER_PROPERTY =
|
||||
"http://xml.org/sax/properties/lexical-handler";
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2012, 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 com.sun.xml.internal.stream.buffer.sax;
|
||||
|
||||
import com.sun.xml.internal.stream.buffer.AbstractCreator;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
import com.sun.xml.internal.stream.buffer.MutableXMLStreamBuffer;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.DTDHandler;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXParseException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
|
||||
/**
|
||||
* Writes into {@link MutableXMLStreamBuffer} from SAX.
|
||||
*
|
||||
* TODO
|
||||
* Implement the marking the stream on the element when an ID
|
||||
* attribute on the element is defined
|
||||
*/
|
||||
public class SAXBufferCreator extends AbstractCreator
|
||||
implements EntityResolver, DTDHandler, ContentHandler, ErrorHandler, LexicalHandler {
|
||||
protected String[] _namespaceAttributes;
|
||||
|
||||
protected int _namespaceAttributesPtr;
|
||||
|
||||
private int depth = 0;
|
||||
|
||||
public SAXBufferCreator() {
|
||||
_namespaceAttributes = new String[16 * 2];
|
||||
}
|
||||
|
||||
public SAXBufferCreator(MutableXMLStreamBuffer buffer) {
|
||||
this();
|
||||
setBuffer(buffer);
|
||||
}
|
||||
|
||||
public MutableXMLStreamBuffer create(XMLReader reader, InputStream in) throws IOException, SAXException {
|
||||
return create(reader, in, null);
|
||||
}
|
||||
|
||||
public MutableXMLStreamBuffer create(XMLReader reader, InputStream in, String systemId) throws IOException, SAXException {
|
||||
if (_buffer == null) {
|
||||
createBuffer();
|
||||
}
|
||||
_buffer.setSystemId(systemId);
|
||||
reader.setContentHandler(this);
|
||||
reader.setProperty(Properties.LEXICAL_HANDLER_PROPERTY, this);
|
||||
|
||||
try {
|
||||
setHasInternedStrings(reader.getFeature(Features.STRING_INTERNING_FEATURE));
|
||||
} catch (SAXException e) {
|
||||
}
|
||||
|
||||
|
||||
if (systemId != null) {
|
||||
InputSource s = new InputSource(systemId);
|
||||
s.setByteStream(in);
|
||||
reader.parse(s);
|
||||
} else {
|
||||
reader.parse(new InputSource(in));
|
||||
}
|
||||
|
||||
return getXMLStreamBuffer();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
_buffer = null;
|
||||
_namespaceAttributesPtr = 0;
|
||||
depth=0;
|
||||
}
|
||||
|
||||
public void startDocument() throws SAXException {
|
||||
storeStructure(T_DOCUMENT);
|
||||
}
|
||||
|
||||
public void endDocument() throws SAXException {
|
||||
storeStructure(T_END);
|
||||
}
|
||||
|
||||
public void startPrefixMapping(String prefix, String uri) throws SAXException {
|
||||
cacheNamespaceAttribute(prefix, uri);
|
||||
}
|
||||
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||
storeQualifiedName(T_ELEMENT_LN,
|
||||
uri, localName, qName);
|
||||
|
||||
// Has namespaces attributes
|
||||
if (_namespaceAttributesPtr > 0) {
|
||||
storeNamespaceAttributes();
|
||||
}
|
||||
|
||||
// Has attributes
|
||||
if (attributes.getLength() > 0) {
|
||||
storeAttributes(attributes);
|
||||
}
|
||||
depth++;
|
||||
}
|
||||
|
||||
public void endElement(String uri, String localName, String qName) throws SAXException {
|
||||
storeStructure(T_END);
|
||||
if(--depth==0)
|
||||
increaseTreeCount(); // one tree processed
|
||||
}
|
||||
|
||||
public void characters(char ch[], int start, int length) throws SAXException {
|
||||
storeContentCharacters(T_TEXT_AS_CHAR_ARRAY, ch, start, length);
|
||||
}
|
||||
|
||||
public void ignorableWhitespace(char ch[], int start, int length) throws SAXException {
|
||||
characters(ch, start, length);
|
||||
}
|
||||
|
||||
public void processingInstruction(String target, String data) throws SAXException {
|
||||
storeStructure(T_PROCESSING_INSTRUCTION);
|
||||
storeStructureString(target);
|
||||
storeStructureString(data);
|
||||
}
|
||||
|
||||
public void comment(char[] ch, int start, int length) throws SAXException {
|
||||
storeContentCharacters(T_COMMENT_AS_CHAR_ARRAY, ch, start, length);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
private void cacheNamespaceAttribute(String prefix, String uri) {
|
||||
_namespaceAttributes[_namespaceAttributesPtr++] = prefix;
|
||||
_namespaceAttributes[_namespaceAttributesPtr++] = uri;
|
||||
|
||||
if (_namespaceAttributesPtr == _namespaceAttributes.length) {
|
||||
final String[] namespaceAttributes = new String[_namespaceAttributesPtr * 2];
|
||||
System.arraycopy(_namespaceAttributes, 0, namespaceAttributes, 0, _namespaceAttributesPtr);
|
||||
_namespaceAttributes = namespaceAttributes;
|
||||
}
|
||||
}
|
||||
|
||||
private void storeNamespaceAttributes() {
|
||||
for (int i = 0; i < _namespaceAttributesPtr; i += 2) {
|
||||
int item = T_NAMESPACE_ATTRIBUTE;
|
||||
if (_namespaceAttributes[i].length() > 0) {
|
||||
item |= FLAG_PREFIX;
|
||||
storeStructureString(_namespaceAttributes[i]);
|
||||
}
|
||||
if (_namespaceAttributes[i + 1].length() > 0) {
|
||||
item |= FLAG_URI;
|
||||
storeStructureString(_namespaceAttributes[i + 1]);
|
||||
}
|
||||
storeStructure(item);
|
||||
}
|
||||
_namespaceAttributesPtr = 0;
|
||||
}
|
||||
|
||||
private void storeAttributes(Attributes attributes) {
|
||||
for (int i = 0; i < attributes.getLength(); i++) {
|
||||
// Skip NS attributes. Some versions of JDK seem to send wrong local name
|
||||
// Also it is not stored correctly by the following.
|
||||
if (attributes.getQName(i).startsWith("xmlns"))
|
||||
continue;
|
||||
storeQualifiedName(T_ATTRIBUTE_LN,
|
||||
attributes.getURI(i),
|
||||
attributes.getLocalName(i),
|
||||
attributes.getQName(i));
|
||||
|
||||
storeStructureString(attributes.getType(i));
|
||||
storeContentString(attributes.getValue(i));
|
||||
}
|
||||
}
|
||||
|
||||
private void storeQualifiedName(int item, String uri, String localName, String qName) {
|
||||
if (uri.length() > 0) {
|
||||
item |= FLAG_URI;
|
||||
storeStructureString(uri);
|
||||
}
|
||||
|
||||
storeStructureString(localName);
|
||||
|
||||
if (qName.indexOf(':') >= 0) {
|
||||
item |= FLAG_QUALIFIED_NAME;
|
||||
storeStructureString(qName);
|
||||
}
|
||||
|
||||
storeStructure(item);
|
||||
}
|
||||
|
||||
|
||||
// Empty methods for SAX handlers
|
||||
|
||||
// Entity resolver handler
|
||||
|
||||
public InputSource resolveEntity (String publicId, String systemId)
|
||||
throws IOException, SAXException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// DTD handler
|
||||
|
||||
public void notationDecl (String name, String publicId, String systemId)
|
||||
throws SAXException
|
||||
{ }
|
||||
|
||||
public void unparsedEntityDecl (String name, String publicId,
|
||||
String systemId, String notationName)
|
||||
throws SAXException
|
||||
{ }
|
||||
|
||||
// Content handler
|
||||
|
||||
public void setDocumentLocator (Locator locator) { }
|
||||
|
||||
public void endPrefixMapping (String prefix) throws SAXException { }
|
||||
|
||||
public void skippedEntity (String name) throws SAXException { }
|
||||
|
||||
// Lexical handler
|
||||
|
||||
public void startDTD(String name, String publicId, String systemId) throws SAXException { }
|
||||
|
||||
public void endDTD() throws SAXException { }
|
||||
|
||||
public void startEntity(String name) throws SAXException { }
|
||||
|
||||
public void endEntity(String name) throws SAXException { }
|
||||
|
||||
public void startCDATA() throws SAXException { }
|
||||
|
||||
public void endCDATA() throws SAXException { }
|
||||
|
||||
// Error handler
|
||||
|
||||
public void warning(SAXParseException e) throws SAXException { }
|
||||
|
||||
public void error(SAXParseException e) throws SAXException { }
|
||||
|
||||
public void fatalError(SAXParseException e) throws SAXException
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,727 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2012, 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 com.sun.xml.internal.stream.buffer.sax;
|
||||
|
||||
import com.sun.xml.internal.stream.buffer.AbstractProcessor;
|
||||
import com.sun.xml.internal.stream.buffer.AttributesHolder;
|
||||
import com.sun.xml.internal.stream.buffer.XMLStreamBuffer;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.DTDHandler;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXNotRecognizedException;
|
||||
import org.xml.sax.SAXNotSupportedException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
import org.xml.sax.helpers.LocatorImpl;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A processor of a {@link XMLStreamBuffer} that that reads the XML infoset as
|
||||
* {@link XMLReader}.
|
||||
*/
|
||||
public class SAXBufferProcessor extends AbstractProcessor implements XMLReader {
|
||||
/**
|
||||
* Reference to entity resolver.
|
||||
*/
|
||||
protected EntityResolver _entityResolver = DEFAULT_LEXICAL_HANDLER;
|
||||
|
||||
/**
|
||||
* Reference to dtd handler.
|
||||
*/
|
||||
protected DTDHandler _dtdHandler = DEFAULT_LEXICAL_HANDLER;
|
||||
|
||||
/**
|
||||
* Reference to content handler.
|
||||
*/
|
||||
protected ContentHandler _contentHandler = DEFAULT_LEXICAL_HANDLER;
|
||||
|
||||
/**
|
||||
* Reference to error handler.
|
||||
*/
|
||||
protected ErrorHandler _errorHandler = DEFAULT_LEXICAL_HANDLER;
|
||||
|
||||
/**
|
||||
* Reference to lexical handler.
|
||||
*/
|
||||
protected LexicalHandler _lexicalHandler = DEFAULT_LEXICAL_HANDLER;
|
||||
|
||||
/**
|
||||
* SAX Namespace attributes features
|
||||
*/
|
||||
protected boolean _namespacePrefixesFeature = false;
|
||||
|
||||
protected AttributesHolder _attributes = new AttributesHolder();
|
||||
|
||||
protected String[] _namespacePrefixes = new String[16];
|
||||
protected int _namespacePrefixesIndex;
|
||||
|
||||
protected int[] _namespaceAttributesStartingStack = new int[16];
|
||||
protected int[] _namespaceAttributesStack = new int[16];
|
||||
protected int _namespaceAttributesStackIndex;
|
||||
|
||||
public SAXBufferProcessor() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Use {@link #SAXBufferProcessor(XMLStreamBuffer, boolean)}
|
||||
*/
|
||||
public SAXBufferProcessor(XMLStreamBuffer buffer) {
|
||||
setXMLStreamBuffer(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param produceFragmentEvent
|
||||
* True to generate fragment SAX events without start/endDocument.
|
||||
* False to generate a full document SAX events.
|
||||
*/
|
||||
public SAXBufferProcessor(XMLStreamBuffer buffer, boolean produceFragmentEvent) {
|
||||
setXMLStreamBuffer(buffer,produceFragmentEvent);
|
||||
}
|
||||
|
||||
public boolean getFeature(String name)
|
||||
throws SAXNotRecognizedException, SAXNotSupportedException {
|
||||
if (name.equals(Features.NAMESPACES_FEATURE)) {
|
||||
return true;
|
||||
} else if (name.equals(Features.NAMESPACE_PREFIXES_FEATURE)) {
|
||||
return _namespacePrefixesFeature;
|
||||
} else if (name.equals(Features.EXTERNAL_GENERAL_ENTITIES)) {
|
||||
return true;
|
||||
} else if (name.equals(Features.EXTERNAL_PARAMETER_ENTITIES)) {
|
||||
return true;
|
||||
} else if (name.equals(Features.STRING_INTERNING_FEATURE)) {
|
||||
return _stringInterningFeature;
|
||||
} else {
|
||||
throw new SAXNotRecognizedException(
|
||||
"Feature not supported: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
public void setFeature(String name, boolean value)
|
||||
throws SAXNotRecognizedException, SAXNotSupportedException {
|
||||
if (name.equals(Features.NAMESPACES_FEATURE)) {
|
||||
if (!value) {
|
||||
throw new SAXNotSupportedException(name + ":" + value);
|
||||
}
|
||||
} else if (name.equals(Features.NAMESPACE_PREFIXES_FEATURE)) {
|
||||
_namespacePrefixesFeature = value;
|
||||
} else if (name.equals(Features.EXTERNAL_GENERAL_ENTITIES)) {
|
||||
// ignore
|
||||
} else if (name.equals(Features.EXTERNAL_PARAMETER_ENTITIES)) {
|
||||
// ignore
|
||||
} else if (name.equals(Features.STRING_INTERNING_FEATURE)) {
|
||||
if (value != _stringInterningFeature) {
|
||||
throw new SAXNotSupportedException(name + ":" + value);
|
||||
}
|
||||
} else {
|
||||
throw new SAXNotRecognizedException(
|
||||
"Feature not supported: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
public Object getProperty(String name)
|
||||
throws SAXNotRecognizedException, SAXNotSupportedException {
|
||||
if (name.equals(Properties.LEXICAL_HANDLER_PROPERTY)) {
|
||||
return getLexicalHandler();
|
||||
} else {
|
||||
throw new SAXNotRecognizedException("Property not recognized: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
public void setProperty(String name, Object value)
|
||||
throws SAXNotRecognizedException, SAXNotSupportedException {
|
||||
if (name.equals(Properties.LEXICAL_HANDLER_PROPERTY)) {
|
||||
if (value instanceof LexicalHandler) {
|
||||
setLexicalHandler((LexicalHandler)value);
|
||||
} else {
|
||||
throw new SAXNotSupportedException(Properties.LEXICAL_HANDLER_PROPERTY);
|
||||
}
|
||||
} else {
|
||||
throw new SAXNotRecognizedException("Property not recognized: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
public void setEntityResolver(EntityResolver resolver) {
|
||||
_entityResolver = resolver;
|
||||
}
|
||||
|
||||
public EntityResolver getEntityResolver() {
|
||||
return _entityResolver;
|
||||
}
|
||||
|
||||
public void setDTDHandler(DTDHandler handler) {
|
||||
_dtdHandler = handler;
|
||||
}
|
||||
|
||||
public DTDHandler getDTDHandler() {
|
||||
return _dtdHandler;
|
||||
}
|
||||
|
||||
public void setContentHandler(ContentHandler handler) {
|
||||
_contentHandler = handler;
|
||||
}
|
||||
|
||||
public ContentHandler getContentHandler() {
|
||||
return _contentHandler;
|
||||
}
|
||||
|
||||
public void setErrorHandler(ErrorHandler handler) {
|
||||
_errorHandler = handler;
|
||||
}
|
||||
|
||||
public ErrorHandler getErrorHandler() {
|
||||
return _errorHandler;
|
||||
}
|
||||
|
||||
public void setLexicalHandler(LexicalHandler handler) {
|
||||
_lexicalHandler = handler;
|
||||
}
|
||||
|
||||
public LexicalHandler getLexicalHandler() {
|
||||
return _lexicalHandler;
|
||||
}
|
||||
|
||||
public void parse(InputSource input) throws IOException, SAXException {
|
||||
// InputSource is ignored
|
||||
process();
|
||||
}
|
||||
|
||||
public void parse(String systemId) throws IOException, SAXException {
|
||||
// systemId is ignored
|
||||
process();
|
||||
}
|
||||
|
||||
/**
|
||||
* Short-hand for {@link #setXMLStreamBuffer(XMLStreamBuffer)} then {@link #process()}.
|
||||
*
|
||||
* @deprecated
|
||||
* Use {@link #process(XMLStreamBuffer, boolean)}
|
||||
*/
|
||||
public final void process(XMLStreamBuffer buffer) throws SAXException {
|
||||
setXMLStreamBuffer(buffer);
|
||||
process();
|
||||
}
|
||||
|
||||
/**
|
||||
* Short-hand for {@link #setXMLStreamBuffer(XMLStreamBuffer,boolean)} then {@link #process()}.
|
||||
*
|
||||
* @param produceFragmentEvent
|
||||
* True to generate fragment SAX events without start/endDocument.
|
||||
* False to generate a full document SAX events.
|
||||
*/
|
||||
public final void process(XMLStreamBuffer buffer, boolean produceFragmentEvent) throws SAXException {
|
||||
setXMLStreamBuffer(buffer);
|
||||
process();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the parser to read from the beginning of the given {@link XMLStreamBuffer}.
|
||||
*
|
||||
* @deprecated
|
||||
* Use {@link #setXMLStreamBuffer(XMLStreamBuffer, boolean)}.
|
||||
*/
|
||||
public void setXMLStreamBuffer(XMLStreamBuffer buffer) {
|
||||
setBuffer(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the parser to read from the beginning of the given {@link XMLStreamBuffer}.
|
||||
*
|
||||
* @param produceFragmentEvent
|
||||
* True to generate fragment SAX events without start/endDocument.
|
||||
* False to generate a full document SAX events.
|
||||
*/
|
||||
public void setXMLStreamBuffer(XMLStreamBuffer buffer, boolean produceFragmentEvent) {
|
||||
if(!produceFragmentEvent && _treeCount>1)
|
||||
throw new IllegalStateException("Can't write a forest to a full XML infoset");
|
||||
setBuffer(buffer,produceFragmentEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the sub-tree (or a whole document) that {@link XMLStreamBuffer}
|
||||
* points to, and sends events to handlers.
|
||||
*
|
||||
* <p>
|
||||
* TODO:
|
||||
* We probably need two modes for a sub-tree event generation. One for
|
||||
* firing a sub-tree as if it's a whole document (in which case start/endDocument
|
||||
* and appropriate additional namespace bindings are necessary), and the other
|
||||
* mode for firing a subtree as a subtree, like it does today.
|
||||
* A stream buffer SAX feature could be used to specify this.
|
||||
*
|
||||
* @throws SAXException
|
||||
* Follow the same semantics as {@link XMLReader#parse(InputSource)}.
|
||||
*/
|
||||
public final void process() throws SAXException {
|
||||
if(!_fragmentMode) {
|
||||
LocatorImpl nullLocator = new LocatorImpl();
|
||||
nullLocator.setSystemId(_buffer.getSystemId());
|
||||
nullLocator.setLineNumber(-1);
|
||||
nullLocator.setColumnNumber(-1);
|
||||
_contentHandler.setDocumentLocator(nullLocator);
|
||||
|
||||
_contentHandler.startDocument();
|
||||
// TODO: if we are writing a fragment stream buffer as a full XML document,
|
||||
// we need to declare in-scope namespaces as if they are on the root element.
|
||||
}
|
||||
|
||||
while (_treeCount>0) {
|
||||
final int item = readEiiState();
|
||||
switch(item) {
|
||||
case STATE_DOCUMENT:
|
||||
processDocument();
|
||||
_treeCount--;
|
||||
break;
|
||||
case STATE_END:
|
||||
// Empty buffer
|
||||
return;
|
||||
case STATE_ELEMENT_U_LN_QN:
|
||||
processElement(readStructureString(), readStructureString(), readStructureString(), isInscope());
|
||||
_treeCount--;
|
||||
break;
|
||||
case STATE_ELEMENT_P_U_LN:
|
||||
{
|
||||
final String prefix = readStructureString();
|
||||
final String uri = readStructureString();
|
||||
final String localName = readStructureString();
|
||||
processElement(uri, localName, getQName(prefix, localName),isInscope());
|
||||
_treeCount--;
|
||||
break;
|
||||
}
|
||||
case STATE_ELEMENT_U_LN: {
|
||||
final String uri = readStructureString();
|
||||
final String localName = readStructureString();
|
||||
processElement(uri, localName, localName,isInscope());
|
||||
_treeCount--;
|
||||
break;
|
||||
}
|
||||
case STATE_ELEMENT_LN:
|
||||
{
|
||||
final String localName = readStructureString();
|
||||
processElement("", localName, localName,isInscope());
|
||||
_treeCount--;
|
||||
break;
|
||||
}
|
||||
case STATE_COMMENT_AS_CHAR_ARRAY_SMALL:
|
||||
processCommentAsCharArraySmall();
|
||||
break;
|
||||
case STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM:
|
||||
processCommentAsCharArrayMedium();
|
||||
break;
|
||||
case STATE_COMMENT_AS_CHAR_ARRAY_COPY:
|
||||
processCommentAsCharArrayCopy();
|
||||
break;
|
||||
case STATE_COMMENT_AS_STRING:
|
||||
processComment(readContentString());
|
||||
break;
|
||||
case STATE_PROCESSING_INSTRUCTION:
|
||||
processProcessingInstruction(readStructureString(), readStructureString());
|
||||
break;
|
||||
default:
|
||||
throw reportFatalError("Illegal state for DIIs: "+item);
|
||||
}
|
||||
}
|
||||
|
||||
if(!_fragmentMode)
|
||||
_contentHandler.endDocument();
|
||||
}
|
||||
|
||||
private void processCommentAsCharArraySmall() throws SAXException {
|
||||
final int length = readStructure();
|
||||
final int start = readContentCharactersBuffer(length);
|
||||
processComment(_contentCharactersBuffer, start, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report a fatal error and abort.
|
||||
*
|
||||
* This is necessary to follow the SAX semantics of error handling.
|
||||
*/
|
||||
private SAXParseException reportFatalError(String msg) throws SAXException {
|
||||
SAXParseException spe = new SAXParseException(msg, null);
|
||||
if(_errorHandler!=null)
|
||||
_errorHandler.fatalError(spe);
|
||||
return spe;
|
||||
}
|
||||
|
||||
private boolean isInscope() {
|
||||
return _buffer.getInscopeNamespaces().size() > 0;
|
||||
}
|
||||
|
||||
private void processDocument() throws SAXException {
|
||||
while(true) {
|
||||
int item = readEiiState();
|
||||
switch(item) {
|
||||
case STATE_ELEMENT_U_LN_QN:
|
||||
processElement(readStructureString(), readStructureString(), readStructureString(),isInscope());
|
||||
break;
|
||||
case STATE_ELEMENT_P_U_LN:
|
||||
{
|
||||
final String prefix = readStructureString();
|
||||
final String uri = readStructureString();
|
||||
final String localName = readStructureString();
|
||||
processElement(uri, localName, getQName(prefix, localName),isInscope());
|
||||
break;
|
||||
}
|
||||
case STATE_ELEMENT_U_LN: {
|
||||
final String uri = readStructureString();
|
||||
final String localName = readStructureString();
|
||||
processElement(uri, localName, localName,isInscope());
|
||||
break;
|
||||
}
|
||||
case STATE_ELEMENT_LN:
|
||||
{
|
||||
final String localName = readStructureString();
|
||||
processElement("", localName, localName,isInscope());
|
||||
break;
|
||||
}
|
||||
case STATE_COMMENT_AS_CHAR_ARRAY_SMALL:
|
||||
processCommentAsCharArraySmall();
|
||||
break;
|
||||
case STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM:
|
||||
processCommentAsCharArrayMedium();
|
||||
break;
|
||||
case STATE_COMMENT_AS_CHAR_ARRAY_COPY:
|
||||
processCommentAsCharArrayCopy();
|
||||
break;
|
||||
case STATE_COMMENT_AS_STRING:
|
||||
processComment(readContentString());
|
||||
break;
|
||||
case STATE_PROCESSING_INSTRUCTION:
|
||||
processProcessingInstruction(readStructureString(), readStructureString());
|
||||
break;
|
||||
case STATE_END:
|
||||
return;
|
||||
default:
|
||||
throw reportFatalError("Illegal state for child of DII: "+item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void processElement(String uri, String localName, String qName, boolean inscope) throws SAXException {
|
||||
boolean hasAttributes = false;
|
||||
boolean hasNamespaceAttributes = false;
|
||||
int item = peekStructure();
|
||||
Set<String> prefixSet = inscope ? new HashSet<String>() : Collections.<String>emptySet();
|
||||
if ((item & TYPE_MASK) == T_NAMESPACE_ATTRIBUTE) {
|
||||
cacheNamespacePrefixStartingIndex();
|
||||
hasNamespaceAttributes = true;
|
||||
item = processNamespaceAttributes(item, inscope, prefixSet);
|
||||
}
|
||||
if (inscope) {
|
||||
readInscopeNamespaces(prefixSet);
|
||||
}
|
||||
|
||||
if ((item & TYPE_MASK) == T_ATTRIBUTE) {
|
||||
hasAttributes = true;
|
||||
processAttributes(item);
|
||||
}
|
||||
|
||||
_contentHandler.startElement(uri, localName, qName, _attributes);
|
||||
|
||||
if (hasAttributes) {
|
||||
_attributes.clear();
|
||||
}
|
||||
|
||||
do {
|
||||
item = readEiiState();
|
||||
switch(item) {
|
||||
case STATE_ELEMENT_U_LN_QN:
|
||||
processElement(readStructureString(), readStructureString(), readStructureString(), false);
|
||||
break;
|
||||
case STATE_ELEMENT_P_U_LN:
|
||||
{
|
||||
final String p = readStructureString();
|
||||
final String u = readStructureString();
|
||||
final String ln = readStructureString();
|
||||
processElement(u, ln, getQName(p, ln),false);
|
||||
break;
|
||||
}
|
||||
case STATE_ELEMENT_U_LN: {
|
||||
final String u = readStructureString();
|
||||
final String ln = readStructureString();
|
||||
processElement(u, ln, ln,false);
|
||||
break;
|
||||
}
|
||||
case STATE_ELEMENT_LN: {
|
||||
final String ln = readStructureString();
|
||||
processElement("", ln, ln,false);
|
||||
break;
|
||||
}
|
||||
case STATE_TEXT_AS_CHAR_ARRAY_SMALL:
|
||||
{
|
||||
final int length = readStructure();
|
||||
int start = readContentCharactersBuffer(length);
|
||||
_contentHandler.characters(_contentCharactersBuffer, start, length);
|
||||
break;
|
||||
}
|
||||
case STATE_TEXT_AS_CHAR_ARRAY_MEDIUM:
|
||||
{
|
||||
final int length = readStructure16();
|
||||
int start = readContentCharactersBuffer(length);
|
||||
_contentHandler.characters(_contentCharactersBuffer, start, length);
|
||||
break;
|
||||
}
|
||||
case STATE_TEXT_AS_CHAR_ARRAY_COPY:
|
||||
{
|
||||
final char[] ch = readContentCharactersCopy();
|
||||
|
||||
_contentHandler.characters(ch, 0, ch.length);
|
||||
break;
|
||||
}
|
||||
case STATE_TEXT_AS_STRING:
|
||||
{
|
||||
final String s = readContentString();
|
||||
_contentHandler.characters(s.toCharArray(), 0, s.length());
|
||||
break;
|
||||
}
|
||||
case STATE_TEXT_AS_OBJECT:
|
||||
{
|
||||
final CharSequence c = (CharSequence)readContentObject();
|
||||
final String s = c.toString();
|
||||
_contentHandler.characters(s.toCharArray(), 0, s.length());
|
||||
break;
|
||||
}
|
||||
case STATE_COMMENT_AS_CHAR_ARRAY_SMALL:
|
||||
processCommentAsCharArraySmall();
|
||||
break;
|
||||
case STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM:
|
||||
processCommentAsCharArrayMedium();
|
||||
break;
|
||||
case STATE_COMMENT_AS_CHAR_ARRAY_COPY:
|
||||
processCommentAsCharArrayCopy();
|
||||
break;
|
||||
case T_COMMENT_AS_STRING:
|
||||
processComment(readContentString());
|
||||
break;
|
||||
case STATE_PROCESSING_INSTRUCTION:
|
||||
processProcessingInstruction(readStructureString(), readStructureString());
|
||||
break;
|
||||
case STATE_END:
|
||||
break;
|
||||
default:
|
||||
throw reportFatalError("Illegal state for child of EII: "+item);
|
||||
}
|
||||
} while(item != STATE_END);
|
||||
|
||||
_contentHandler.endElement(uri, localName, qName);
|
||||
|
||||
if (hasNamespaceAttributes) {
|
||||
processEndPrefixMapping();
|
||||
}
|
||||
}
|
||||
|
||||
private void readInscopeNamespaces(Set<String> prefixSet) throws SAXException {
|
||||
for (Map.Entry<String, String> e : _buffer.getInscopeNamespaces().entrySet()) {
|
||||
String key = fixNull(e.getKey());
|
||||
// If the prefix is already written, do not write the prefix
|
||||
if (!prefixSet.contains(key)) {
|
||||
processNamespaceAttribute(key,e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static String fixNull(String s) {
|
||||
if (s == null) return "";
|
||||
else return s;
|
||||
}
|
||||
private void processCommentAsCharArrayCopy() throws SAXException {
|
||||
final char[] ch = readContentCharactersCopy();
|
||||
processComment(ch, 0, ch.length);
|
||||
}
|
||||
|
||||
private void processCommentAsCharArrayMedium() throws SAXException {
|
||||
final int length = readStructure16();
|
||||
final int start = readContentCharactersBuffer(length);
|
||||
processComment(_contentCharactersBuffer, start, length);
|
||||
}
|
||||
|
||||
private void processEndPrefixMapping() throws SAXException {
|
||||
final int end = _namespaceAttributesStack[--_namespaceAttributesStackIndex];
|
||||
// final int start = (_namespaceAttributesStackIndex > 0) ? _namespaceAttributesStack[_namespaceAttributesStackIndex] : 0;
|
||||
final int start = (_namespaceAttributesStackIndex >= 0) ? _namespaceAttributesStartingStack[_namespaceAttributesStackIndex] : 0;
|
||||
|
||||
for (int i = end - 1; i >= start; i--) {
|
||||
_contentHandler.endPrefixMapping(_namespacePrefixes[i]);
|
||||
}
|
||||
_namespacePrefixesIndex = start;
|
||||
}
|
||||
|
||||
private int processNamespaceAttributes(int item,boolean collectPrefixes, Set<String> prefixSet) throws SAXException {
|
||||
do {
|
||||
String prefix;
|
||||
switch(getNIIState(item)) {
|
||||
case STATE_NAMESPACE_ATTRIBUTE:
|
||||
// Undeclaration of default namespace
|
||||
processNamespaceAttribute("", "");
|
||||
if(collectPrefixes) {
|
||||
prefixSet.add("");
|
||||
}
|
||||
break;
|
||||
case STATE_NAMESPACE_ATTRIBUTE_P:
|
||||
// Undeclaration of namespace
|
||||
prefix = readStructureString();
|
||||
processNamespaceAttribute(prefix, "");
|
||||
if(collectPrefixes) {
|
||||
prefixSet.add(prefix);
|
||||
}
|
||||
break;
|
||||
case STATE_NAMESPACE_ATTRIBUTE_P_U:
|
||||
// Declaration with prefix
|
||||
prefix = readStructureString();
|
||||
processNamespaceAttribute(prefix, readStructureString());
|
||||
if(collectPrefixes) {
|
||||
prefixSet.add(prefix);
|
||||
}
|
||||
break;
|
||||
case STATE_NAMESPACE_ATTRIBUTE_U:
|
||||
// Default declaration
|
||||
processNamespaceAttribute("", readStructureString());
|
||||
if(collectPrefixes) {
|
||||
prefixSet.add("");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw reportFatalError("Illegal state: "+item);
|
||||
}
|
||||
readStructure();
|
||||
|
||||
item = peekStructure();
|
||||
} while((item & TYPE_MASK) == T_NAMESPACE_ATTRIBUTE);
|
||||
|
||||
|
||||
cacheNamespacePrefixIndex();
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
private void processAttributes(int item) throws SAXException {
|
||||
do {
|
||||
switch(getAIIState(item)) {
|
||||
case STATE_ATTRIBUTE_U_LN_QN:
|
||||
_attributes.addAttributeWithQName(readStructureString(), readStructureString(), readStructureString(), readStructureString(), readContentString());
|
||||
break;
|
||||
case STATE_ATTRIBUTE_P_U_LN:
|
||||
{
|
||||
final String p = readStructureString();
|
||||
final String u = readStructureString();
|
||||
final String ln = readStructureString();
|
||||
_attributes.addAttributeWithQName(u, ln, getQName(p, ln), readStructureString(), readContentString());
|
||||
break;
|
||||
}
|
||||
case STATE_ATTRIBUTE_U_LN: {
|
||||
final String u = readStructureString();
|
||||
final String ln = readStructureString();
|
||||
_attributes.addAttributeWithQName(u, ln, ln, readStructureString(), readContentString());
|
||||
break;
|
||||
}
|
||||
case STATE_ATTRIBUTE_LN: {
|
||||
final String ln = readStructureString();
|
||||
_attributes.addAttributeWithQName("", ln, ln, readStructureString(), readContentString());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw reportFatalError("Illegal state: "+item);
|
||||
}
|
||||
readStructure();
|
||||
|
||||
item = peekStructure();
|
||||
} while((item & TYPE_MASK) == T_ATTRIBUTE);
|
||||
}
|
||||
|
||||
private void processNamespaceAttribute(String prefix, String uri) throws SAXException {
|
||||
_contentHandler.startPrefixMapping(prefix, uri);
|
||||
|
||||
if (_namespacePrefixesFeature) {
|
||||
// Add the namespace delcaration as an attribute
|
||||
if (prefix != "") {
|
||||
_attributes.addAttributeWithQName(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, prefix,
|
||||
getQName(XMLConstants.XMLNS_ATTRIBUTE, prefix),
|
||||
"CDATA", uri);
|
||||
} else {
|
||||
_attributes.addAttributeWithQName(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, XMLConstants.XMLNS_ATTRIBUTE,
|
||||
XMLConstants.XMLNS_ATTRIBUTE,
|
||||
"CDATA", uri);
|
||||
}
|
||||
}
|
||||
|
||||
cacheNamespacePrefix(prefix);
|
||||
}
|
||||
|
||||
private void cacheNamespacePrefix(String prefix) {
|
||||
if (_namespacePrefixesIndex == _namespacePrefixes.length) {
|
||||
final String[] namespaceAttributes = new String[_namespacePrefixesIndex * 3 / 2 + 1];
|
||||
System.arraycopy(_namespacePrefixes, 0, namespaceAttributes, 0, _namespacePrefixesIndex);
|
||||
_namespacePrefixes = namespaceAttributes;
|
||||
}
|
||||
|
||||
_namespacePrefixes[_namespacePrefixesIndex++] = prefix;
|
||||
}
|
||||
|
||||
private void cacheNamespacePrefixIndex() {
|
||||
if (_namespaceAttributesStackIndex == _namespaceAttributesStack.length) {
|
||||
final int[] namespaceAttributesStack = new int[_namespaceAttributesStackIndex * 3 /2 + 1];
|
||||
System.arraycopy(_namespaceAttributesStack, 0, namespaceAttributesStack, 0, _namespaceAttributesStackIndex);
|
||||
_namespaceAttributesStack = namespaceAttributesStack;
|
||||
}
|
||||
|
||||
_namespaceAttributesStack[_namespaceAttributesStackIndex++] = _namespacePrefixesIndex;
|
||||
}
|
||||
|
||||
private void cacheNamespacePrefixStartingIndex() {
|
||||
if (_namespaceAttributesStackIndex == _namespaceAttributesStartingStack.length) {
|
||||
final int[] namespaceAttributesStart = new int[_namespaceAttributesStackIndex * 3 /2 + 1];
|
||||
System.arraycopy(_namespaceAttributesStartingStack, 0, namespaceAttributesStart, 0, _namespaceAttributesStackIndex);
|
||||
_namespaceAttributesStartingStack = namespaceAttributesStart;
|
||||
}
|
||||
_namespaceAttributesStartingStack[_namespaceAttributesStackIndex] = _namespacePrefixesIndex;
|
||||
}
|
||||
|
||||
private void processComment(String s) throws SAXException {
|
||||
processComment(s.toCharArray(), 0, s.length());
|
||||
}
|
||||
|
||||
private void processComment(char[] ch, int start, int length) throws SAXException {
|
||||
_lexicalHandler.comment(ch, start, length);
|
||||
}
|
||||
|
||||
private void processProcessingInstruction(String target, String data) throws SAXException {
|
||||
_contentHandler.processingInstruction(target, data);
|
||||
}
|
||||
|
||||
private static final DefaultWithLexicalHandler DEFAULT_LEXICAL_HANDLER = new DefaultWithLexicalHandler();
|
||||
}
|
||||
Reference in New Issue
Block a user