GUAC-340: Expose available protocols within Environment.

This commit is contained in:
Michael Jumper
2014-11-23 17:39:48 -08:00
parent ff286264e4
commit 49b91ebe56
23 changed files with 222 additions and 155 deletions

View File

@@ -0,0 +1,200 @@
/*
* Copyright (C) 2013 Glyptodon LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.glyptodon.guacamole.xml;
import java.util.Deque;
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 Deque<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() {
// If no state, return null
if (stack.isEmpty())
return null;
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);
}
// If no handler returned, the element was not expected
if (handler == null)
throw new SAXException("Unexpected element: '" + localName + "'");
// Initialize handler
handler.init(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 static 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;
}
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright (C) 2013 Glyptodon LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.glyptodon.guacamole.xml;
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.
* @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)
throws SAXException;
/**
* Called when the element corresponding to this TagHandler is first seen,
* just after an instance is created.
*
* @param attributes The attributes of the element seen.
* @throws SAXException If an error prevents a the TagHandler from being
* from being initialized.
*/
public void init(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;
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright (C) 2013 Glyptodon LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* Classes driving the SAX-based XML parser used by the Guacamole web
* application.
*/
package org.glyptodon.guacamole.xml;

View File

@@ -0,0 +1,65 @@
/*
* Copyright (C) 2013 Glyptodon LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.glyptodon.guacamole.xml.protocol;
import org.glyptodon.guacamole.protocols.ProtocolParameterOption;
import org.glyptodon.guacamole.xml.TagHandler;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
/**
* TagHandler for the "option" element.
*
* @author Mike Jumper
*/
public class OptionTagHandler implements TagHandler {
/**
* The option backing this option tag.
*/
private ProtocolParameterOption option = new ProtocolParameterOption();
@Override
public void init(Attributes attributes) throws SAXException {
option.setValue(attributes.getValue("value"));
}
@Override
public TagHandler childElement(String localName) throws SAXException {
throw new SAXException("The 'param' tag can contain no elements.");
}
@Override
public void complete(String textContent) throws SAXException {
option.setTitle(textContent);
}
/**
* Returns the ProtocolParameterOption backing this tag.
* @return The ProtocolParameterOption backing this tag.
*/
public ProtocolParameterOption asProtocolParameterOption() {
return option;
}
}

View File

@@ -0,0 +1,124 @@
/*
* Copyright (C) 2013 Glyptodon LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.glyptodon.guacamole.xml.protocol;
import org.glyptodon.guacamole.protocols.ProtocolParameter;
import org.glyptodon.guacamole.xml.TagHandler;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
/**
* TagHandler for the "param" element.
*
* @author Mike Jumper
*/
public class ParamTagHandler implements TagHandler {
/**
* The ProtocolParameter backing this tag handler.
*/
private ProtocolParameter protocolParameter = new ProtocolParameter();
@Override
public void init(Attributes attributes) throws SAXException {
protocolParameter.setName(attributes.getValue("name"));
protocolParameter.setTitle(attributes.getValue("title"));
protocolParameter.setValue(attributes.getValue("value"));
// Parse type
String type = attributes.getValue("type");
// Text field
if ("text".equals(type))
protocolParameter.setType(ProtocolParameter.Type.TEXT);
// Numeric field
else if ("numeric".equals(type))
protocolParameter.setType(ProtocolParameter.Type.NUMERIC);
// Username field
else if ("username".equals(type))
protocolParameter.setType(ProtocolParameter.Type.USERNAME);
// Password field
else if ("password".equals(type))
protocolParameter.setType(ProtocolParameter.Type.PASSWORD);
// Enumerated field
else if ("enum".equals(type))
protocolParameter.setType(ProtocolParameter.Type.ENUM);
// Multiline field
else if ("multiline".equals(type))
protocolParameter.setType(ProtocolParameter.Type.MULTILINE);
// Boolean field
else if ("boolean".equals(type)) {
protocolParameter.setType(ProtocolParameter.Type.BOOLEAN);
if(protocolParameter.getValue() == null)
throw new SAXException
("A value is required for the boolean parameter type.");
}
// Otherwise, fail with unrecognized type
else
throw new SAXException("Invalid parameter type: " + type);
}
@Override
public TagHandler childElement(String localName) throws SAXException {
// Start parsing of option tags
if (localName.equals("option")) {
// Get tag handler for option tag
OptionTagHandler tagHandler = new OptionTagHandler();
// Store stub in options collection
protocolParameter.getOptions().add(
tagHandler.asProtocolParameterOption());
return tagHandler;
}
return null;
}
@Override
public void complete(String textContent) throws SAXException {
// Do nothing
}
/**
* Returns the ProtocolParameter backing this tag.
* @return The ProtocolParameter backing this tag.
*/
public ProtocolParameter asProtocolParameter() {
return protocolParameter;
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (C) 2013 Glyptodon LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.glyptodon.guacamole.xml.protocol;
import org.glyptodon.guacamole.protocols.ProtocolInfo;
import org.glyptodon.guacamole.xml.TagHandler;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
/**
* TagHandler for the "protocol" element.
*
* @author Mike Jumper
*/
public class ProtocolTagHandler implements TagHandler {
/**
* The ProtocolInfo object which will contain all data parsed by this tag
* handler.
*/
private ProtocolInfo info = new ProtocolInfo();
@Override
public void init(Attributes attributes) throws SAXException {
info.setName(attributes.getValue("name"));
info.setTitle(attributes.getValue("title"));
}
@Override
public TagHandler childElement(String localName) throws SAXException {
// Start parsing of param tags, add to list of all parameters
if (localName.equals("param")) {
// Get tag handler for param tag
ParamTagHandler tagHandler = new ParamTagHandler();
// Store stub in parameters collection
info.getParameters().add(tagHandler.asProtocolParameter());
return tagHandler;
}
return null;
}
@Override
public void complete(String textContent) throws SAXException {
// Do nothing
}
/**
* Returns the ProtocolInfo backing this tag.
* @return The ProtocolInfo backing this tag.
*/
public ProtocolInfo asProtocolInfo() {
return info;
}
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright (C) 2013 Glyptodon LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* Classes related to parsing XML files which describe the parameters of a
* protocol.
*/
package org.glyptodon.guacamole.xml.protocol;