diff options
Diffstat (limited to 'src/com/isode/stroke/parser/BOSHBodyExtractor.java')
-rw-r--r-- | src/com/isode/stroke/parser/BOSHBodyExtractor.java | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/src/com/isode/stroke/parser/BOSHBodyExtractor.java b/src/com/isode/stroke/parser/BOSHBodyExtractor.java new file mode 100644 index 0000000..6b637b1 --- /dev/null +++ b/src/com/isode/stroke/parser/BOSHBodyExtractor.java @@ -0,0 +1,174 @@ +/* Copyright (c) 2016, Isode Limited, London, England. + * All rights reserved. + * + * Acquisition and use of this software and related materials for any + * purpose requires a written license agreement from Isode Limited, + * or a written license from an organisation licensed by Isode Limited + * to grant such a license. + * + */ +package com.isode.stroke.parser; + +import java.util.Arrays; + +import com.isode.stroke.base.ByteArray; + +public class BOSHBodyExtractor { + + private BOSHBody body = null; + + public BOSHBodyExtractor(XMLParserFactory parserFactory,ByteArray data) { + // Look for the opening body element + byte[] rawData = data.getData(); + int i = 0; + while (i < rawData.length && isWhitespace((char) rawData[i])) { + ++i; + } + if ((rawData.length - i) < 6 || rawData[i] != '<' || rawData[i+1] != 'b' + || rawData[i+2] != 'o' || rawData[i+3] != 'd' || rawData[i+4] != 'y' + || !isEndCharacter((char) rawData[i+5])) { + return; + } + i += 5; + + + // Parse until end of element + boolean inSingleQuote = false; + boolean inDoubleQuote = false; + boolean endStartTagSeen = false; + boolean endElementSeen = false; + + for (; i < rawData.length; ++i) { + char c = (char) rawData[i]; + if (inSingleQuote) { + if (c == '\'') { + inSingleQuote = false; + } + } + else if (inDoubleQuote) { + if (c == '"') { + inDoubleQuote = false; + } + } + else if (c == '\'') { + inSingleQuote = true; + } + else if (c == '"') { + inDoubleQuote = true; + } + else if (c == '/') { + if (i + 1 == rawData.length || rawData[i+1] != '>') { + return; + } + else { + endElementSeen = true; + endStartTagSeen = true; + i += 2; + break; + } + } + else if (c == '>') { + endStartTagSeen = true; + i += 1; + break; + } + } + + if (!endStartTagSeen) { + return; + } + + // Look for the end of the element + + int j = rawData.length - 1; + if (!endElementSeen) { + while (isWhitespace((char) rawData[j]) && j > -1) { + j--; + } + + if (j == -1 || rawData[j] != '>') { + return; + } + j--; + + while (j > -1 && isWhitespace((char) rawData[j])) { + j--; + } + + if (j < 6 || rawData[j-5] != '<' || rawData[j-4] != '/' || rawData[j-3] != 'b' + || rawData[j-2] != 'o' || rawData[j-1] != 'd' || rawData[j] != 'y' ) { + return; + } + + j -= 6; + } + + body = new BOSHBody(); + + if (!endElementSeen) { + byte[] rawBodyContent = + Arrays.copyOfRange(rawData, i, j+1); + body.content = (new ByteArray(rawBodyContent)).toString(); + } + + BOSHBodyParserClient parserClient = new BOSHBodyParserClient(this); + XMLParser parser = parserFactory.createParser(parserClient); + String stringToParse = data.toString().substring(0, i); + if(!parser.parse(stringToParse)) { + body = null; + } + } + + public static boolean isWhitespace(char c) { + return c == ' ' || c == '\n' || c == '\t' || c == '\r'; + } + + private static boolean isEndCharacter(char c) { + return isWhitespace(c) || c == '>' || c == '/'; + } + + public BOSHBody getBody() { + return body; + } + + public static class BOSHBody { + private AttributeMap attributes = new AttributeMap(); + private String content = ""; + + public AttributeMap getAttributes() { + return attributes; + } + + public String getContent() { + return content; + } + + } + + private final static class BOSHBodyParserClient implements XMLParserClient { + + private BOSHBodyParserClient(BOSHBodyExtractor bodyExtractor) { + bodyExtractor_ = bodyExtractor; + } + + @Override + public void handleStartElement(String element, String ns, + AttributeMap attributes) { + bodyExtractor_.body.attributes = attributes; + } + + @Override + public void handleEndElement(String element, String ns) { + // Empty Method + } + + @Override + public void handleCharacterData(String data) { + // Empty Method + } + + private final BOSHBodyExtractor bodyExtractor_; + + } + +} |