/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.cxf.jaxb;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.ws.RequestWrapper;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import com.sun.xml.bind.marshaller.NamespacePrefixMapper;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.jaxb_form.ObjectWithQualifiedElementElement;
import org.apache.cxf.jaxb_misc.Base64WithDefaultValueType;
import org.apache.cxf.jaxb_misc.ObjectFactory;
import org.apache.cxf.service.model.MessagePartInfo;
import org.apache.cxf.staxutils.StaxStreamFilter;
import org.apache.cxf.testutil.common.TestUtil;
import org.apache.hello_world_soap_http.Greeter;
import org.apache.hello_world_soap_http.types.GreetMe;
import org.apache.hello_world_soap_http.types.GreetMeResponse;
import org.apache.hello_world_soap_http.types.StringStruct;
import org.apache.type_test.doc.TypeTestPortType;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* JAXBEncoderDecoderTest
* @author apaibir
*/
public class JAXBEncoderDecoderTest extends Assert {
public static final QName SOAP_ENV =
new QName("http://schemas.xmlsoap.org/soap/envelope/", "Envelope");
public static final QName SOAP_BODY =
new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body");
RequestWrapper wrapperAnnotation;
JAXBContext context;
Schema schema;
private Map<String, Object> emptyMarshallerProperties = Collections.emptyMap();
@Before
public void setUp() throws Exception {
context = JAXBContext.newInstance(new Class[] {
GreetMe.class,
GreetMeResponse.class,
StringStruct.class,
ObjectWithQualifiedElementElement.class
});
Method method = TestUtil.getMethod(Greeter.class, "greetMe");
wrapperAnnotation = method.getAnnotation(RequestWrapper.class);
InputStream is = getClass().getResourceAsStream("resources/StringStruct.xsd");
StreamSource schemaSource = new StreamSource(is);
assertNotNull(schemaSource);
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
schema = factory.newSchema(schemaSource);
assertNotNull(schema);
}
@Test
public void testMarshallIntoDOM() throws Exception {
String str = new String("Hello");
QName inCorrectElName = new QName("http://test_jaxb_marshall", "requestType");
MessagePartInfo part = new MessagePartInfo(inCorrectElName, null);
part.setElement(true);
part.setElementQName(inCorrectElName);
Document doc = DOMUtils.createDocument();
Element elNode = doc.createElementNS(inCorrectElName.getNamespaceURI(),
inCorrectElName.getLocalPart());
assertNotNull(elNode);
Node node;
try {
JAXBEncoderDecoder.marshall(context, null, null, part, elNode, emptyMarshallerProperties);
fail("Should have thrown a Fault");
} catch (Fault ex) {
//expected - not a valid object
}
GreetMe obj = new GreetMe();
obj.setRequestType("Hello");
QName elName = new QName(wrapperAnnotation.targetNamespace(),
wrapperAnnotation.localName());
part.setElementQName(elName);
JAXBEncoderDecoder.marshall(context, null, obj, part, elNode, emptyMarshallerProperties);
node = elNode.getLastChild();
//The XML Tree Looks like
//<GreetMe><requestType>Hello</requestType></GreetMe>
assertEquals(Node.ELEMENT_NODE, node.getNodeType());
Node childNode = node.getFirstChild();
assertEquals(Node.ELEMENT_NODE, childNode.getNodeType());
childNode = childNode.getFirstChild();
assertEquals(Node.TEXT_NODE, childNode.getNodeType());
assertEquals(str, childNode.getNodeValue());
// Now test schema validation during marshaling
StringStruct stringStruct = new StringStruct();
// Don't initialize one of the structure members.
//stringStruct.setArg0("hello");
stringStruct.setArg1("world");
// Marshal without the schema should work.
JAXBEncoderDecoder.marshall(context, null, stringStruct, part, elNode, emptyMarshallerProperties);
try {
// Marshal with the schema should get an exception.
JAXBEncoderDecoder.marshall(context, schema, stringStruct, part, elNode,
emptyMarshallerProperties);
fail("Marshal with schema should have thrown a Fault");
} catch (Fault ex) {
//expected - not a valid object
}
}
@Test
public void testMarshallWithFormQualifiedElement() throws Exception {
ObjectWithQualifiedElementElement testObject = new ObjectWithQualifiedElementElement();
testObject.setString1("twine");
testObject.setString2("cord");
QName elName = new QName(wrapperAnnotation.targetNamespace(),
wrapperAnnotation.localName());
MessagePartInfo part = new MessagePartInfo(elName, null);
part.setElement(true);
part.setElementQName(elName);
StringWriter stringWriter = new StringWriter();
XMLOutputFactory opFactory = XMLOutputFactory.newInstance();
opFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE);
XMLEventWriter writer = opFactory.createXMLEventWriter(stringWriter);
JAXBEncoderDecoder.marshall(context, null, testObject, part, writer, emptyMarshallerProperties);
writer.flush();
writer.close();
String xmlResult = stringWriter.toString();
// the following is a bit of a crock, but, to tell the truth, this test case most exists
// so that it could be examined inside the debugger to see how JAXB works.
assertTrue(xmlResult.contains("ns3:string2"));
}
@Test
public void testCustomNamespaces() throws Exception {
Map<String, Object> marshallProps = new HashMap<String, Object>();
NamespacePrefixMapper mapper = new NamespacePrefixMapper() {
@Override
public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
if ("http://apache.org/hello_world_soap_http/types".equals(namespaceUri)) {
return "Omnia";
} else if ("http://cxf.apache.org/jaxb_form".equals(namespaceUri)) {
return "Gallia";
}
return suggestion;
}
};
marshallProps.put("com.sun.xml.bind.namespacePrefixMapper", mapper);
ObjectWithQualifiedElementElement testObject = new ObjectWithQualifiedElementElement();
testObject.setString1("twine");
testObject.setString2("cord");
QName elName = new QName(wrapperAnnotation.targetNamespace(),
wrapperAnnotation.localName());
MessagePartInfo part = new MessagePartInfo(elName, null);
part.setElement(true);
part.setElementQName(elName);
StringWriter stringWriter = new StringWriter();
XMLOutputFactory opFactory = XMLOutputFactory.newInstance();
opFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE);
XMLEventWriter writer = opFactory.createXMLEventWriter(stringWriter);
JAXBEncoderDecoder.marshall(context, null, testObject, part, writer, marshallProps);
writer.flush();
writer.close();
String xmlResult = stringWriter.toString();
// the following is a bit of a crock, but, to tell the truth, this test case most exists
// so that it could be examined inside the debugger to see how JAXB works.
assertTrue(xmlResult.contains("Gallia:string2"));
}
@Test
public void testMarshallIntoStax() throws Exception {
GreetMe obj = new GreetMe();
obj.setRequestType("Hello");
QName elName = new QName(wrapperAnnotation.targetNamespace(),
wrapperAnnotation.localName());
MessagePartInfo part = new MessagePartInfo(elName, null);
part.setElement(true);
part.setElementQName(elName);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
XMLOutputFactory opFactory = XMLOutputFactory.newInstance();
opFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE);
XMLEventWriter writer = opFactory.createXMLEventWriter(baos);
//STARTDOCUMENT/ENDDOCUMENT is not required
//writer.add(eFactory.createStartDocument("utf-8", "1.0"));
JAXBEncoderDecoder.marshall(context, null, obj, part, writer, emptyMarshallerProperties);
//writer.add(eFactory.createEndDocument());
writer.flush();
writer.close();
//System.out.println(baos.toString());
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
XMLInputFactory ipFactory = XMLInputFactory.newInstance();
XMLEventReader reader = ipFactory.createXMLEventReader(bais);
Unmarshaller um = context.createUnmarshaller();
Object val = um.unmarshal(reader, GreetMe.class);
assertTrue(val instanceof JAXBElement);
val = ((JAXBElement)val).getValue();
assertTrue(val instanceof GreetMe);
assertEquals(obj.getRequestType(),
((GreetMe)val).getRequestType());
}
@Test
public void testUnmarshallFromStax() throws Exception {
QName elName = new QName(wrapperAnnotation.targetNamespace(),
wrapperAnnotation.localName());
MessagePartInfo part = new MessagePartInfo(elName, null);
InputStream is = getClass().getResourceAsStream("resources/GreetMeDocLiteralReq.xml");
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader =
factory.createXMLStreamReader(is);
QName[] tags = {SOAP_ENV, SOAP_BODY};
StaxStreamFilter filter = new StaxStreamFilter(tags);
reader = factory.createFilteredReader(reader, filter);
//Remove START_DOCUMENT & START_ELEMENT pertaining to Envelope and Body Tags.
part.setTypeClass(GreetMe.class);
Object val = JAXBEncoderDecoder.unmarshall(context, null, reader, part, null, true);
assertNotNull(val);
assertTrue(val instanceof GreetMe);
assertEquals("TestSOAPInputPMessage",
((GreetMe)val).getRequestType());
is.close();
}
@Test
public void testMarshalRPCLit() throws Exception {
QName elName = new QName("http://test_jaxb_marshall", "in");
MessagePartInfo part = new MessagePartInfo(elName, null);
part.setElement(true);
part.setElementQName(elName);
Document doc = DOMUtils.createDocument();
Element elNode = doc.createElementNS(elName.getNamespaceURI(),
elName.getLocalPart());
JAXBEncoderDecoder.marshall(context, null,
new String("TestSOAPMessage"), part, elNode, emptyMarshallerProperties);
assertNotNull(elNode.getChildNodes());
assertEquals("TestSOAPMessage", elNode.getFirstChild().getFirstChild().getNodeValue());
}
@Test
public void testUnMarshall() throws Exception {
//Hello World Wsdl generated namespace
QName elName = new QName(wrapperAnnotation.targetNamespace(),
wrapperAnnotation.localName());
MessagePartInfo part = new MessagePartInfo(elName, null);
part.setElement(true);
part.setElementQName(elName);
part.setTypeClass(Class.forName(wrapperAnnotation.className()));
Document doc = DOMUtils.createDocument();
Element elNode = doc.createElementNS(elName.getNamespaceURI(),
elName.getLocalPart());
Element rtEl = doc.createElementNS(elName.getNamespaceURI(), "requestType");
elNode.appendChild(rtEl);
rtEl.appendChild(doc.createTextNode("Hello Test"));
Object obj = JAXBEncoderDecoder.unmarshall(context, null,
elNode, part, null, true);
assertNotNull(obj);
//Add a Node and then test
assertEquals(GreetMe.class, obj.getClass());
assertEquals("Hello Test", ((GreetMe)obj).getRequestType());
part.setTypeClass(String.class);
Node n = null;
try {
JAXBEncoderDecoder.unmarshall(context, null, n, part, null, true);
fail("Should have received a Fault");
} catch (Fault pe) {
//Expected Exception
} catch (Exception ex) {
fail("Should have received a Fault, not: " + ex);
}
// Now test schema validation during unmarshaling
elName = new QName(wrapperAnnotation.targetNamespace(),
"stringStruct");
// Create an XML Tree of
// <StringStruct><arg1>World</arg1></StringStruct>
// elNode = soapElFactory.createElement(elName);
// elNode.addNamespaceDeclaration("", elName.getNamespaceURI());
part = new MessagePartInfo(elName, null);
part.setElement(true);
part.setElementQName(elName);
part.setTypeClass(Class.forName("org.apache.hello_world_soap_http.types.StringStruct"));
doc = DOMUtils.createDocument();
elNode = doc.createElementNS(elName.getNamespaceURI(),
elName.getLocalPart());
rtEl = doc.createElementNS(elName.getNamespaceURI(), "arg1");
elNode.appendChild(rtEl);
rtEl.appendChild(doc.createTextNode("World"));
// Should unmarshal without problems when no schema used.
obj = JAXBEncoderDecoder.unmarshall(context, null, elNode, part, null, true);
assertNotNull(obj);
assertEquals(StringStruct.class, obj.getClass());
assertEquals("World", ((StringStruct)obj).getArg1());
try {
// unmarshal with schema should raise exception.
obj = JAXBEncoderDecoder.unmarshall(context, schema, elNode, part, null, true);
fail("Should have thrown a Fault");
} catch (Fault ex) {
// expected - schema validation should fail.
}
}
@Test
public void testUnmarshallWithoutClzInfo() throws Exception {
QName elName = new QName(wrapperAnnotation.targetNamespace(),
wrapperAnnotation.localName());
Document doc = DOMUtils.createDocument();
Element elNode = doc.createElementNS(elName.getNamespaceURI(),
elName.getLocalPart());
Element rtEl = doc.createElementNS(elName.getNamespaceURI(), "requestType");
elNode.appendChild(rtEl);
rtEl.appendChild(doc.createTextNode("Hello Test"));
Object obj = JAXBEncoderDecoder.unmarshall(context, null, elNode);
assertNotNull(obj);
assertEquals(GreetMe.class, obj.getClass());
assertEquals("Hello Test", ((GreetMe)obj).getRequestType());
}
@Test
public void testMarshallWithoutQNameInfo() throws Exception {
GreetMe obj = new GreetMe();
obj.setRequestType("Hello");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
XMLOutputFactory opFactory = XMLOutputFactory.newInstance();
opFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE);
XMLEventWriter writer = opFactory.createXMLEventWriter(baos);
//STARTDOCUMENT/ENDDOCUMENT is not required
//writer.add(eFactory.createStartDocument("utf-8", "1.0"));
JAXBEncoderDecoder.marshall(context, null, obj, writer, emptyMarshallerProperties);
//writer.add(eFactory.createEndDocument());
writer.flush();
writer.close();
//System.out.println(baos.toString());
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
XMLInputFactory ipFactory = XMLInputFactory.newInstance();
XMLEventReader reader = ipFactory.createXMLEventReader(bais);
Unmarshaller um = context.createUnmarshaller();
Object val = um.unmarshal(reader, GreetMe.class);
assertTrue(val instanceof JAXBElement);
val = ((JAXBElement)val).getValue();
assertTrue(val instanceof GreetMe);
assertEquals(obj.getRequestType(),
((GreetMe)val).getRequestType());
}
@Test
public void testGetClassFromType() throws Exception {
Method testByte = TestUtil.getMethod(TypeTestPortType.class, "testByte");
Type[] genericParameterTypes = testByte.getGenericParameterTypes();
Class<?>[] paramTypes = testByte.getParameterTypes();
int idx = 0;
for (Type t : genericParameterTypes) {
Class<?> cls = JAXBEncoderDecoder.getClassFromType(t);
assertTrue(cls.equals(paramTypes[idx]));
idx++;
}
Method testBase64Binary = TestUtil.getMethod(TypeTestPortType.class, "testBase64Binary");
genericParameterTypes = testBase64Binary.getGenericParameterTypes();
paramTypes = testBase64Binary.getParameterTypes();
idx = 0;
for (Type t : genericParameterTypes) {
Class<?> cls = JAXBEncoderDecoder.getClassFromType(t);
assertTrue(cls.equals(paramTypes[idx]));
idx++;
}
}
@Test
public void testDefaultValueConverter() throws Exception {
Base64WithDefaultValueType testData = (new ObjectFactory()).createBase64WithDefaultValueType();
byte[] checkValue = testData.getAttributeWithDefaultValue();
assertNotNull(checkValue);
}
}