Search in sources :

Example 21 with XMLElement

use of com.zimbra.common.soap.Element.XMLElement in project zm-mailbox by Zimbra.

the class JaxbToJsonTest method kvpForGetDLRespWithOwner.

/**
 * Ensuring that JAXB can handle having an owner in a list that is not an empty array when there are no owners
 */
@Test
public void kvpForGetDLRespWithOwner() throws Exception {
    Element jsonElem = JSONElement.mFactory.createElement(QName.get(AccountConstants.E_GET_DISTRIBUTION_LIST_RESPONSE, AccountConstants.NAMESPACE_STR));
    populateGetDlResp(jsonElem);
    Element xmlElem = XMLElement.mFactory.createElement(QName.get(AccountConstants.E_GET_DISTRIBUTION_LIST_RESPONSE, AccountConstants.NAMESPACE_STR));
    populateGetDlResp(xmlElem);
    logDebug("XmlElement (for comparison) ---> prettyPrint\n%1$s", xmlElem.prettyPrint());
    logDebug("JSONElement (for comparison) ---> prettyPrint\n%1$s", jsonElem.prettyPrint());
    List<KeyValuePair> attrs = Lists.newArrayList();
    attrs.add(new KeyValuePair("mail", "fun@example.test"));
    attrs.add(new KeyValuePair("zimbraMailStatus", "enabled"));
    DistributionListInfo dl = new DistributionListInfo("myId", "my name", null, attrs);
    dl.setDynamic(true);
    DistributionListGranteeInfo grantee = new DistributionListGranteeInfo(GranteeType.usr, "ownerId", "ownerName");
    dl.addOwner(grantee);
    GetDistributionListResponse jaxb = new GetDistributionListResponse(dl);
    Element xmlJaxbElem = JaxbUtil.jaxbToElement(jaxb, XMLElement.mFactory);
    Element jsonJaxbElem = JacksonUtil.jaxbToJSONElement(jaxb);
    GetDistributionListResponse roundtripped = JaxbUtil.elementToJaxb(jsonJaxbElem, GetDistributionListResponse.class);
    GetDistributionListResponse roundtrippedX = JaxbUtil.elementToJaxb(xmlJaxbElem, GetDistributionListResponse.class);
    logDebug("JSONElement from JAXB ---> prettyPrint\n%1$s", jsonJaxbElem.prettyPrint());
    logDebug("XMLElement from JAXB ---> prettyPrint\n%1$s", xmlJaxbElem.prettyPrint());
    List<? extends KeyValuePair> kvps = roundtripped.getDl().getAttrList();
    Assert.assertEquals("roundtripped kvps num", 2, kvps.size());
    Assert.assertEquals("roundtripped owner num", 1, roundtripped.getDl().getOwners().size());
    Assert.assertEquals("roundtrippedX owner num", 1, roundtrippedX.getDl().getOwners().size());
}
Also used : GetDistributionListResponse(com.zimbra.soap.account.message.GetDistributionListResponse) DistributionListInfo(com.zimbra.soap.account.type.DistributionListInfo) KeyValuePair(com.zimbra.soap.type.KeyValuePair) DistributionListGranteeInfo(com.zimbra.soap.account.type.DistributionListGranteeInfo) XmlAnyElement(javax.xml.bind.annotation.XmlAnyElement) Element(com.zimbra.common.soap.Element) XMLElement(com.zimbra.common.soap.Element.XMLElement) JSONElement(com.zimbra.common.soap.Element.JSONElement) XmlElement(javax.xml.bind.annotation.XmlElement) FilterTest(com.zimbra.soap.mail.type.FilterTest) Test(org.junit.Test)

Example 22 with XMLElement

use of com.zimbra.common.soap.Element.XMLElement in project zm-mailbox by Zimbra.

the class JaxbToElementTest method ConvActionRequestJaxbSubclassHandlingTestDisabled.

/**
 * Explore handling of Jaxb classes which specify an @XmlElement with
 * a super class.  How do subclasses get treated with this?
 * WSDLJaxbTest.ConvActionRequestJaxbSubclassHandlingTest passes,
 * i.e. it successfully unmarshalls to a ConvActionRequest with
 * a FolderActionSelector member.
 * However, even if I use those class files (with package name changed)
 * in place of the committed ones, this test only seems to unmarshall
 * with an ActionSelector member - i.e. the "recursive" and "url"
 * attribute information gets lost.
 */
// @Test
public void ConvActionRequestJaxbSubclassHandlingTestDisabled() throws Exception {
    ConvActionSelector actionSelector = ConvActionSelector.createForIdsAndOperation("ids", "op");
    actionSelector.setAcctRelativePath("folder");
    ConvActionRequest car = new ConvActionRequest(actionSelector);
    Element carE = JaxbUtil.jaxbToElement(car);
    String eXml = carE.toString();
    ZimbraLog.test.debug("ConvActionRequestJaxbSubclassHandling: marshalled XML=%s", eXml);
    Assert.assertTrue("Xml should contain acctRelPath attribute", eXml.contains("acctRelPath=\"folder\""));
    carE = Element.XMLElement.mFactory.createElement(MailConstants.CONV_ACTION_REQUEST);
    Element actionE = carE.addNonUniqueElement(MailConstants.E_ACTION);
    actionE.addAttribute(MailConstants.A_OPERATION, "op");
    actionE.addAttribute(MailConstants.A_ID, "ids");
    actionE.addAttribute(MailConstants.A_ACCT_RELATIVE_PATH, "folder");
    ZimbraLog.test.debug("ConvActionRequestJaxbSubclassHandling: half baked XML=%s", carE.toString());
    car = JaxbUtil.elementToJaxb(carE);
    carE = JaxbUtil.jaxbToElement(car);
    eXml = carE.toString();
    ZimbraLog.test.debug("ConvActionRequestJaxbSubclassHandling: round tripped XML=%s", eXml);
    ConvActionSelector as = car.getAction();
    Assert.assertEquals("acctRelPath attr value", "folder", as.getAcctRelativePath());
}
Also used : ConvActionSelector(com.zimbra.soap.mail.type.ConvActionSelector) ConvActionRequest(com.zimbra.soap.mail.message.ConvActionRequest) Element(com.zimbra.common.soap.Element) XMLElement(com.zimbra.common.soap.Element.XMLElement) JSONElement(com.zimbra.common.soap.Element.JSONElement) JAXBElement(javax.xml.bind.JAXBElement)

Example 23 with XMLElement

use of com.zimbra.common.soap.Element.XMLElement in project zm-mailbox by Zimbra.

the class JaxbUtil method fixupStructureForJaxb.

/**
 * Manipulates a structure under {@link elem} which obeys Zimbra's SOAP XML structure rules to comply with more
 * stringent JAXB rules.
 * <ol>
 * <li>Zimbra allows attributes to be specified as elements.
 * <p>One scenario where this happens - {@link XMLElement}'s {@code getAttribute(String key, String defaultValue)}
 * will look for an attribute with "key" as the name.
 * If it fails to find that, it looks for an element with "key" as the name and returns the elements text.</p></li>
 * <li>Zimbra allows elements to be specified as attributes.
 * <p>One scenario where this happens.
 * <pre>
 *      elem.addAttribute("xml-elem-json-attr", "XML elem but JSON attribute", Element.Disposition.CONTENT);
 * </pre>
 * Will be serialized to this JSON (i.e. treated as an attribute in JSON) :
 * <pre>
 *       "xml-elem-json-attr": "XML elem but JSON attribute"
 * </pre>
 * or to this XML (i.e. treated as an element in XML) :
 * <pre>
 *       &lt;xml-elem-json-attr>XML elem but JSON attribute&lt;/xml-elem-json-attr>
 * </pre>
 * In JAXB, we typically use {@link XmlElement} for the associated field.  Round tripping from XML will result in
 * an element but round tripping from JSON will result in an attribute.
 * <li>Zimbra uses key/value pairs which serialize to JSON as:
 * <pre>
 *     "_attrs":{"anID":"val","anID2":"val2"}
 * </pre>
 * If this is read into a JSONElement structure and written out as XML, you get:
 * <pre>
 *     &lt;a n="anID">val&lt;/a>&lt;a n="anID2">val2&lt;/a>
 * </pre>
 * The element name "a" and the attribute name "n" are defaults - the actual expected values can be different - so
 * we query the JAXB classes to see what they should be.
 * </ol>
 * @param klass is the JAXB class for {@code elem} which must be under the "com.zimbra" package hierarchy.
 */
private static void fixupStructureForJaxb(org.w3c.dom.Element elem, Class<?> klass) {
    if (elem == null) {
        return;
    }
    if (klass == null) {
        LOG.debug("JAXB no class associated with " + elem.getLocalName());
        return;
    }
    if (!isJaxbType(klass)) {
        return;
    }
    JaxbInfo jaxbInfo = JaxbInfo.getFromCache(klass);
    NamedNodeMap attrs = elem.getAttributes();
    int numAttrs = attrs.getLength();
    List<String> orphanAttrs = null;
    // Process each attribute
    for (int i = 0; i < numAttrs; i++) {
        Attr attr = (Attr) attrs.item(i);
        // Get attribute name and value
        String attrName = attr.getNodeName();
        if (!jaxbInfo.hasAttribute(attrName) && jaxbInfo.hasElement(attrName)) {
            if (orphanAttrs == null) {
                orphanAttrs = Lists.newArrayList();
            }
            orphanAttrs.add(attrName);
            String attrValue = attr.getNodeValue();
            elem.getNamespaceURI();
            org.w3c.dom.Element newElem = elem.getOwnerDocument().createElementNS(elem.getNamespaceURI(), attrName);
            newElem.setTextContent(attrValue);
            elem.appendChild(newElem);
        }
    }
    if (orphanAttrs != null) {
        for (String orphan : orphanAttrs) {
            attrs.removeNamedItem(orphan);
        }
    }
    NodeList list = elem.getChildNodes();
    List<org.w3c.dom.Element> orphans = null;
    for (int i = 0; i < list.getLength(); i++) {
        Node subnode = list.item(i);
        if (subnode.getNodeType() == Node.ELEMENT_NODE) {
            org.w3c.dom.Element child = (org.w3c.dom.Element) subnode;
            String childName = child.getLocalName();
            if (jaxbInfo.hasWrapperElement(childName)) {
                NodeList wrappedList = child.getChildNodes();
                for (int j = 0; j < wrappedList.getLength(); j++) {
                    Node wSubnode = wrappedList.item(j);
                    if (wSubnode.getNodeType() == Node.ELEMENT_NODE) {
                        org.w3c.dom.Element wChild = (org.w3c.dom.Element) wSubnode;
                        fixupStructureForJaxb(wChild, jaxbInfo.getClassForWrappedElement(childName, wChild.getLocalName()));
                    }
                }
            } else if (jaxbInfo.hasElement(childName)) {
                fixupStructureForJaxb(child, jaxbInfo.getClassForElement(childName));
            } else if (jaxbInfo.hasAttribute(childName)) {
                elem.setAttribute(childName, child.getTextContent());
                // Don't remove pre-existing child until later pass to avoid changing the list of child elements
                if (orphans == null) {
                    orphans = Lists.newArrayList();
                }
                orphans.add(child);
            } else if (Element.XMLElement.E_ATTRIBUTE.equals(childName)) {
                // This might be a keyvaluepair, the Element code doesn't have access to JAXB info, so defaults
                // the element name to "a" and its attribute will be "n".  If this is what has happened, replace
                // it with a corrected equivalent using the JAXB object for reference.
                JaxbInfo.KeyValuePairXmlRepresentationInfo kvpXmlRep = jaxbInfo.getKeyValuePairElementInfo();
                if (kvpXmlRep != null) {
                    elem.getNamespaceURI();
                    org.w3c.dom.Element newElem = elem.getOwnerDocument().createElementNS(elem.getNamespaceURI(), kvpXmlRep.getXmlElementName());
                    newElem.setTextContent(child.getTextContent());
                    newElem.setAttribute(kvpXmlRep.getXmlAttributeName(), child.getAttribute(Element.XMLElement.A_ATTR_NAME));
                    elem.appendChild(newElem);
                    if (orphans == null) {
                        orphans = Lists.newArrayList();
                    }
                    orphans.add(child);
                }
            } else {
                LOG.debug("JAXB class " + klass.getName() + " does NOT recognise element named:" + childName);
            }
        }
    }
    // Prune the promoted elements from the list of children
    if (orphans != null) {
        for (org.w3c.dom.Element orphan : orphans) {
            elem.removeChild(orphan);
        }
    }
}
Also used : NamedNodeMap(org.w3c.dom.NamedNodeMap) NodeList(org.w3c.dom.NodeList) Element(com.zimbra.common.soap.Element) JSONElement(com.zimbra.common.soap.Element.JSONElement) JAXBElement(javax.xml.bind.JAXBElement) XMLElement(com.zimbra.common.soap.Element.XMLElement) Node(org.w3c.dom.Node) Attr(org.w3c.dom.Attr) JaxbInfo(com.zimbra.soap.util.JaxbInfo)

Example 24 with XMLElement

use of com.zimbra.common.soap.Element.XMLElement in project zm-mailbox by Zimbra.

the class JaxbUtil method addChildElementFromJaxb.

public static Element addChildElementFromJaxb(Element parent, String name, String namespace, Object o) {
    Element.ElementFactory factory;
    if (parent instanceof XMLElement) {
        factory = XMLElement.mFactory;
    } else {
        factory = JSONElement.mFactory;
    }
    Element child = null;
    try {
        child = jaxbToNamedElement(name, namespace, o, factory);
    } catch (ServiceException e) {
        ZimbraLog.misc.info("JAXB Problem making " + name + " element", e);
    }
    parent.addElement(child);
    return child;
}
Also used : ServiceException(com.zimbra.common.service.ServiceException) Element(com.zimbra.common.soap.Element) JSONElement(com.zimbra.common.soap.Element.JSONElement) JAXBElement(javax.xml.bind.JAXBElement) XMLElement(com.zimbra.common.soap.Element.XMLElement) XMLElement(com.zimbra.common.soap.Element.XMLElement)

Example 25 with XMLElement

use of com.zimbra.common.soap.Element.XMLElement in project zm-mailbox by Zimbra.

the class JaxbToJsonTest method wrapperAbsentIfEmpty.

/**
 * How to achieve a wrapped list where no element for the wrapper will appear in the XML if the list is empty.
 * This no longer works!  Fortunately, looks like we don't use any classes similar to WrapperAbsentIfEmpty
 * at the moment.
 * For JUDASPRIEST/Java 7 setNumbers is called with 2 integers.  For main/Java 8
 * it is called with an empty list.
 *     WrapperAbsentIfEmpty.setNumbers(List<Integer>) line: 51
 *     WrapperAbsentIfEmpty$JaxbAccessorM_getNumbers_setNumbers_java_util_List.set(Object, Object) line: 60
 *     Lister$CollectionLister<BeanT,T>.startPacking(BeanT, Accessor<BeanT,T>) line: 298
 *     Lister$CollectionLister<BeanT,T>.startPacking(Object, Accessor) line: 269
 *     Scope<BeanT,PropT,ItemT,PackT>.start(Accessor<BeanT,PropT>, Lister<BeanT,PropT,ItemT,PackT>) line: 142
 *     ArrayERProperty$ItemsLoader.startElement(UnmarshallingContext$State, TagName) line: 119
 *     UnmarshallingContext._startElement(TagName) line: 501
 *     UnmarshallingContext.startElement(TagName) line: 480
 *     InterningXmlVisitor.startElement(TagName) line: 75
 *     SAXConnector.startElement(String, String, String, Attributes) line: 150
 *     DOMScanner.visit(Element) line: 244
 *     DOMScanner.visit(Node) line: 281
 *     DOMScanner.visit(Element) line: 250
 *     DOMScanner.scan(Element) line: 127
 *     UnmarshallerImpl.unmarshal0(Node, JaxBeanInfo) line: 369
 *     UnmarshallerImpl.unmarshal(Node, Class<T>) line: 348
 *     JaxbUtil.rawW3cDomDocToJaxb(Document, Class<?>, boolean) line: 1420
 *     JaxbUtil.w3cDomDocToJaxb(Document, Class<?>, boolean) line: 1392
 *     JaxbUtil.elementToJaxb(Element, Class<?>) line: 1438
 *     JaxbToJsonTest.wrapperAbsentIfEmpty() line: 1516
 */
@Ignore("Bug:95509 - this is hypothetical functionality that isn't currently used, so low priority")
@Test
public void wrapperAbsentIfEmpty() throws Exception {
    WrapperAbsentIfEmpty jaxb = new WrapperAbsentIfEmpty();
    Element jsonJaxbElem = JacksonUtil.jaxbToJSONElement(jaxb);
    WrapperAbsentIfEmpty roundtripped = JaxbUtil.elementToJaxb(jsonJaxbElem, WrapperAbsentIfEmpty.class);
    logDebug("JSONElement from JAXB (empty numbers)--> prettyPrint\n%1$s", jsonJaxbElem.prettyPrint());
    Assert.assertNull("original getNumbers (empty list)", jaxb.getNumbers());
    Assert.assertNull("JSON roundtripped getNumbers (empty list)", roundtripped.getNumbers());
    Assert.assertEquals("JSON for empty Numbers", "{\n  \"_jsns\": \"urn:zimbraTest\"\n}", jsonJaxbElem.prettyPrint());
    Element xmlElem = JaxbUtil.jaxbToElement(jaxb, Element.XMLElement.mFactory, true, false);
    logDebug("XmlElement from JAXB (empty numbers) ---> prettyPrint\n%1$s", xmlElem.prettyPrint());
    WrapperAbsentIfEmpty roundtrippedX = JaxbUtil.elementToJaxb(xmlElem, WrapperAbsentIfEmpty.class);
    Assert.assertNull("XML roundtripped getNumbers (empty list)", roundtrippedX.getNumbers());
    Assert.assertEquals("XML for empty Numbers", "<wrapper-absent-if-empty xmlns=\"urn:zimbraTest\"/>", xmlElem.prettyPrint());
    jaxb.addNumber(314159);
    jaxb.addNumber(42);
    jsonJaxbElem = JacksonUtil.jaxbToJSONElement(jaxb);
    roundtripped = JaxbUtil.elementToJaxb(jsonJaxbElem, WrapperAbsentIfEmpty.class);
    logDebug("JSONElement from JAXB (empty numbers)--> prettyPrint\n%1$s", jsonJaxbElem.prettyPrint());
    Assert.assertEquals("original size of Numbers (2 numbers)", 2, jaxb.getNumbers().size());
    Assert.assertNotNull("XML roundtripped getNumbers (when 2 numbers in list)", roundtrippedX.getNumbers());
    Assert.assertEquals("JSON roundtripped size of Numbers (2 numbers)", 2, roundtripped.getNumbers().size());
    xmlElem = JaxbUtil.jaxbToElement(jaxb, Element.XMLElement.mFactory, true, false);
    logDebug("XmlElement from JAXB (empty numbers) ---> prettyPrint\n%1$s", xmlElem.prettyPrint());
    roundtrippedX = JaxbUtil.elementToJaxb(xmlElem, WrapperAbsentIfEmpty.class);
    Assert.assertEquals("XML roundtripped size of Numbers (2 numbers)", 2, roundtrippedX.getNumbers().size());
    Assert.assertEquals("XML when have 2 numbers", String.format("%s\n  %s\n    %s\n    %s\n  %s\n%s", "<wrapper-absent-if-empty xmlns=\"urn:zimbraTest\">", "<numbers>", "<number>314159</number>", "<number>42</number>", "</numbers>", "</wrapper-absent-if-empty>"), xmlElem.prettyPrint());
}
Also used : XmlAnyElement(javax.xml.bind.annotation.XmlAnyElement) Element(com.zimbra.common.soap.Element) XMLElement(com.zimbra.common.soap.Element.XMLElement) JSONElement(com.zimbra.common.soap.Element.JSONElement) XmlElement(javax.xml.bind.annotation.XmlElement) WrapperAbsentIfEmpty(com.zimbra.soap.jaxb.WrapperAbsentIfEmpty) Ignore(org.junit.Ignore) FilterTest(com.zimbra.soap.mail.type.FilterTest) Test(org.junit.Test)

Aggregations

XMLElement (com.zimbra.common.soap.Element.XMLElement)146 Element (com.zimbra.common.soap.Element)116 JSONElement (com.zimbra.common.soap.Element.JSONElement)33 Test (org.junit.Test)32 XmlAnyElement (javax.xml.bind.annotation.XmlAnyElement)28 XmlElement (javax.xml.bind.annotation.XmlElement)28 FilterTest (com.zimbra.soap.mail.type.FilterTest)26 SoapHttpTransport (com.zimbra.common.soap.SoapHttpTransport)9 HashMap (java.util.HashMap)8 KeyValuePair (com.zimbra.soap.type.KeyValuePair)7 ArrayList (java.util.ArrayList)7 Account (com.zimbra.cs.account.Account)6 ZAuthToken (com.zimbra.common.auth.ZAuthToken)5 ByteBuilder (com.zimbra.common.mime.HeaderUtils.ByteBuilder)4 ServiceException (com.zimbra.common.service.ServiceException)4 DataSource (com.zimbra.cs.account.DataSource)4 Auth (com.zimbra.cs.service.account.Auth)4 URL (java.net.URL)4 Cookie (javax.servlet.http.Cookie)4 HttpException (org.apache.http.HttpException)4