From 980d0ff116b7aa7d49fece1904f34f0b11076346 Mon Sep 17 00:00:00 2001 From: Scott Battaglia Date: Sun, 6 Jan 2013 23:40:46 -0500 Subject: [PATCH 1/2] CASC-196 real XML parsing example if using . Updated tests to make sure it works if there are line breaks. --- .../Cas20ServiceTicketValidator.java | 87 ++++++++++++++----- .../Cas20ServiceTicketValidatorTests.java | 3 +- 2 files changed, 69 insertions(+), 21 deletions(-) diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java index 627ca9a..f4ffa50 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java @@ -27,7 +27,16 @@ import org.jasig.cas.client.proxy.ProxyRetriever; import org.jasig.cas.client.util.CommonUtils; import org.jasig.cas.client.util.XmlUtils; import org.w3c.dom.NodeList; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.DefaultHandler; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import java.io.StringReader; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -128,27 +137,18 @@ public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTick * @return the map of attributes. */ protected Map extractCustomAttributes(final String xml) { - - if (!xml.contains("")) { - return new HashMap(); - } - - final Map attributes = new HashMap(); - + final SAXParserFactory spf = SAXParserFactory.newInstance(); + spf.setNamespaceAware(true); + spf.setValidating(false); try { - NodeList nodeList = XmlUtils.getNodeListForElements(xml,"cas:attributes"); - for (int i = 0; i < nodeList.getLength(); i++) { - final String nodeName = nodeList.item(i).getNodeName(); - final int beginIndex = nodeName.indexOf(":") + 1; - final int endIndex = nodeList.item(i).getNodeName().length(); - - final String attributeName = nodeName.substring(beginIndex, endIndex); // remove the "cas:" prefix from node name - final Object attributeValue = nodeList.item(i).getTextContent(); - attributes.put(attributeName, attributeValue); - } - return attributes; - - } catch (Exception e) { + final SAXParser saxParser = spf.newSAXParser(); + final XMLReader xmlReader = saxParser.getXMLReader(); + final CustomAttributeHandler handler = new CustomAttributeHandler(); + xmlReader.setContentHandler(handler); + xmlReader.parse(new InputSource(new StringReader(xml))); + return handler.getAttributes(); + } catch (final Exception e) { + log.error(e.getMessage(), e); return Collections.emptyMap(); } } @@ -187,4 +187,51 @@ public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTick protected final ProxyRetriever getProxyRetriever() { return this.proxyRetriever; } + + private class CustomAttributeHandler extends DefaultHandler { + + private Map attributes; + + private boolean foundAttributes; + + private String currentAttribute; + + private StringBuilder value; + + @Override + public void startDocument() throws SAXException { + this.attributes = new HashMap(); + } + + @Override + public void startElement(final String namespaceURI, final String localName, final String qName, final Attributes attributes) throws SAXException { + if ("attributes".equals(localName)) { + this.foundAttributes = true; + } else if (this.foundAttributes) { + this.value = new StringBuilder(); + this.currentAttribute = localName; + } + } + + @Override + public void characters(final char[] chars, final int start, final int length) throws SAXException { + if (this.currentAttribute != null) { + value.append(chars, start, length); + } + } + + @Override + public void endElement(final String namespaceURI, final String localName, final String qName) throws SAXException { + if ("attributes".equals(localName)) { + this.foundAttributes = false; + this.currentAttribute = null; + } else if (this.foundAttributes) { + this.attributes.put(currentAttribute, value.toString()); + } + } + + public Map getAttributes() { + return this.attributes; + } + } } diff --git a/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidatorTests.java b/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidatorTests.java index c250969..0b1f137 100644 --- a/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidatorTests.java +++ b/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidatorTests.java @@ -139,13 +139,14 @@ public final class Cas20ServiceTicketValidatorTests extends AbstractTicketValida + USERNAME + "" + PGTIOU - + "testid"; + + "testidtest1\n\ntest"; server.content = RESPONSE.getBytes(server.encoding); final Assertion assertion = this.ticketValidator.validate("test", "test"); assertEquals(USERNAME, assertion.getPrincipal().getName()); assertEquals("test", assertion.getPrincipal().getAttributes().get("password")); assertEquals("id", assertion.getPrincipal().getAttributes().get("eduPersonId")); + assertEquals("test1\n\ntest", assertion.getPrincipal().getAttributes().get("longAttribute")); //assertEquals(PGT, assertion.getProxyGrantingTicketId()); } From 67bb0a6ef83801a26d3e3898884aa10a429f6245 Mon Sep 17 00:00:00 2001 From: Scott Battaglia Date: Mon, 7 Jan 2013 23:10:24 -0500 Subject: [PATCH 2/2] CASC-196 re-add support for multi-valued attributes --- .../Cas20ServiceTicketValidator.java | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java index f4ffa50..99637ac 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java @@ -36,10 +36,7 @@ import org.xml.sax.helpers.DefaultHandler; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import java.io.StringReader; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; +import java.util.*; /** * Implementation of the TicketValidator that will validate Service Tickets in compliance with the CAS 2. @@ -226,7 +223,21 @@ public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTick this.foundAttributes = false; this.currentAttribute = null; } else if (this.foundAttributes) { - this.attributes.put(currentAttribute, value.toString()); + final Object o = this.attributes.get(this.currentAttribute); + + if (o == null) { + this.attributes.put(this.currentAttribute, this.value.toString()); + } else { + final List items; + if (o instanceof List) { + items = (List) o; + } else { + items = new LinkedList(); + items.add(o); + this.attributes.put(this.currentAttribute, items); + } + items.add(this.value.toString()); + } } }