mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-07 13:41:21 +00:00
Implement MUCH simpler SAX-driven XML parser.
This commit is contained in:
@@ -0,0 +1,183 @@
|
|||||||
|
package net.sourceforge.guacamole.net.basic.xml;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Guacamole - Clientless Remote Desktop
|
||||||
|
* Copyright (C) 2010 Michael Jumper
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import org.xml.sax.Attributes;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
import org.xml.sax.helpers.DefaultHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple ContentHandler implementation which digests SAX document events and
|
||||||
|
* produces simpler tag-level events, maintaining its own stack for the
|
||||||
|
* convenience of the tag handlers.
|
||||||
|
*
|
||||||
|
* @author Mike Jumper
|
||||||
|
*/
|
||||||
|
public class DocumentHandler extends DefaultHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the root element of the document.
|
||||||
|
*/
|
||||||
|
private String rootElementName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The handler which will be used to handle element events for the root
|
||||||
|
* element of the document.
|
||||||
|
*/
|
||||||
|
private TagHandler root;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The stack of all states applicable to the current parser state. Each
|
||||||
|
* element of the stack references the TagHandler for the element being
|
||||||
|
* parsed at that level of the document, where the current element is
|
||||||
|
* last in the stack, and the root element is first.
|
||||||
|
*/
|
||||||
|
private LinkedList<DocumentHandlerState> stack =
|
||||||
|
new LinkedList<DocumentHandlerState>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new DocumentHandler which will use the given TagHandler
|
||||||
|
* to handle the root element.
|
||||||
|
*
|
||||||
|
* @param rootElementName The name of the root element of the document
|
||||||
|
* being handled.
|
||||||
|
* @param root The TagHandler to use for the root element.
|
||||||
|
*/
|
||||||
|
public DocumentHandler(String rootElementName, TagHandler root) {
|
||||||
|
this.root = root;
|
||||||
|
this.rootElementName = rootElementName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current element state. The current element state is the
|
||||||
|
* state of the element the parser is currently within.
|
||||||
|
*
|
||||||
|
* @return The current element state.
|
||||||
|
*/
|
||||||
|
private DocumentHandlerState getCurrentState() {
|
||||||
|
return stack.getLast();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startElement(String uri, String localName, String qName,
|
||||||
|
Attributes attributes) throws SAXException {
|
||||||
|
|
||||||
|
// Get current state
|
||||||
|
DocumentHandlerState current = getCurrentState();
|
||||||
|
|
||||||
|
// Handler for tag just read
|
||||||
|
TagHandler handler;
|
||||||
|
|
||||||
|
// If no stack, use root handler
|
||||||
|
if (current == null) {
|
||||||
|
|
||||||
|
// Validate element name
|
||||||
|
if (!localName.equals(rootElementName))
|
||||||
|
throw new SAXException("Root element must be '" + rootElementName + "'");
|
||||||
|
|
||||||
|
handler = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, get handler from parent
|
||||||
|
else {
|
||||||
|
TagHandler parent_handler = current.getTagHandler();
|
||||||
|
handler = parent_handler.childElement(localName, attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append new element state to stack
|
||||||
|
stack.addLast(new DocumentHandlerState(handler));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void endElement(String uri, String localName, String qName)
|
||||||
|
throws SAXException {
|
||||||
|
|
||||||
|
// Pop last element from stack
|
||||||
|
DocumentHandlerState completed = stack.removeLast();
|
||||||
|
|
||||||
|
// Finish element by sending text content
|
||||||
|
completed.getTagHandler().complete(
|
||||||
|
completed.getTextContent().toString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void characters(char[] ch, int start, int length)
|
||||||
|
throws SAXException {
|
||||||
|
|
||||||
|
// Append received chunk to text content
|
||||||
|
getCurrentState().getTextContent().append(ch, start, length);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current state of the DocumentHandler.
|
||||||
|
*/
|
||||||
|
private class DocumentHandlerState {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current text content of the current element being parsed.
|
||||||
|
*/
|
||||||
|
private StringBuilder textContent = new StringBuilder();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The TagHandler which must handle document events related to the
|
||||||
|
* element currently being parsed.
|
||||||
|
*/
|
||||||
|
private TagHandler tagHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new DocumentHandlerState which will maintain the state
|
||||||
|
* of parsing of the current element, as well as contain the TagHandler
|
||||||
|
* which will receive events related to that element.
|
||||||
|
*
|
||||||
|
* @param tagHandler The TagHandler which should receive any events
|
||||||
|
* related to the element being parsed.
|
||||||
|
*/
|
||||||
|
public DocumentHandlerState(TagHandler tagHandler) {
|
||||||
|
this.tagHandler = tagHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the mutable StringBuilder which contains the current text
|
||||||
|
* content of the element being parsed.
|
||||||
|
*
|
||||||
|
* @return The mutable StringBuilder which contains the current text
|
||||||
|
* content of the element being parsed.
|
||||||
|
*/
|
||||||
|
public StringBuilder getTextContent() {
|
||||||
|
return textContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the TagHandler which must handle any events relating to the
|
||||||
|
* element being parsed.
|
||||||
|
*
|
||||||
|
* @return The TagHandler which must handle any events relating to the
|
||||||
|
* element being parsed.
|
||||||
|
*/
|
||||||
|
public TagHandler getTagHandler() {
|
||||||
|
return tagHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,57 @@
|
|||||||
|
package net.sourceforge.guacamole.net.basic.xml;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Guacamole - Clientless Remote Desktop
|
||||||
|
* Copyright (C) 2010 Michael Jumper
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.xml.sax.Attributes;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple element-level event handler for events triggered by the
|
||||||
|
* SAX-driven DocumentHandler parser.
|
||||||
|
*
|
||||||
|
* @author Mike Jumper
|
||||||
|
*/
|
||||||
|
public interface TagHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a child element of the current element is parsed.
|
||||||
|
*
|
||||||
|
* @param localName The local name of the child element seen.
|
||||||
|
* @param attributes The attributes of the child element seen.
|
||||||
|
* @return The TagHandler which should handle all element-level events
|
||||||
|
* related to the child element.
|
||||||
|
* @throws SAXException If the child element being parsed was not expected,
|
||||||
|
* or some other error prevents a proper TagHandler
|
||||||
|
* from being constructed for the child element.
|
||||||
|
*/
|
||||||
|
public TagHandler childElement(String localName, Attributes attributes)
|
||||||
|
throws SAXException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when this element, and all child elements, have been fully parsed,
|
||||||
|
* and the entire text content of this element (if any) is available.
|
||||||
|
*
|
||||||
|
* @param textContent The full text content of this element, if any.
|
||||||
|
* @throws SAXException If the text content received is not valid for any
|
||||||
|
* reason, or the child elements parsed are not
|
||||||
|
* correct.
|
||||||
|
*/
|
||||||
|
public void complete(String textContent) throws SAXException;
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user