/**
* 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.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
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 javax.xml.ws.ResponseWrapper;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
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.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.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* JAXBEncoderDecoderTest
*/
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;
Map<String, String> mapField;
String arrayField[];
List<String> listField;
@Before
public void setUp() throws Exception {
context = JAXBContext.newInstance(new Class[] {
GreetMe.class,
GreetMeResponse.class,
StringStruct.class,
ObjectWithQualifiedElementElement.class
});
Method method = getMethod("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);
}
private Method getMethod(String methodName) {
Method[] declMethods = this.getClass().getDeclaredMethods();
for (Method method : declMethods) {
if (method.getName().equals(methodName)) {
return method;
}
}
return null;
}
@RequestWrapper(localName = "greetMe",
targetNamespace = "http://apache.org/hello_world_soap_http/types",
className = "org.apache.hello_world_soap_http.types.GreetMe")
@ResponseWrapper(localName = "greetMeResponse",
targetNamespace = "http://apache.org/hello_world_soap_http/types",
className = "org.apache.hello_world_soap_http.types.GreetMeResponse")
public java.lang.String greetMe(
java.lang.String requestType
) {
return "Hello " + requestType;
}
private Type getFieldType(String name) throws Exception {
return this.getClass()
.getDeclaredField(name)
.getGenericType();
}
@Test
public void testCXF3611() throws Exception {
Map<String, String> foo = new HashMap<String, String>();
assertTrue(JAXBSchemaInitializer.isArray(getFieldType("arrayField")));
assertTrue(JAXBSchemaInitializer.isArray(getFieldType("listField")));
assertFalse(JAXBSchemaInitializer.isArray(foo.getClass()));
assertFalse(JAXBSchemaInitializer.isArray(getFieldType("mapField")));
}
@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.createMarshaller(), null, part, elNode);
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.createMarshaller(), obj, part, elNode);
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.createMarshaller(), stringStruct, part, elNode);
try {
Marshaller m = context.createMarshaller();
m.setSchema(schema);
// Marshal with the schema should get an exception.
JAXBEncoderDecoder.marshall(m, stringStruct, part, elNode);
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.createMarshaller(), testObject, part, writer);
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, String> mapper = new HashMap<String, String>();
mapper.put("http://apache.org/hello_world_soap_http/types", "Omnia");
mapper.put("http://cxf.apache.org/jaxb_form", "Gallia");
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);
Marshaller m = context.createMarshaller();
JAXBUtils.setNamespaceWrapper(mapper, m);
JAXBEncoderDecoder.marshall(m, testObject, part, writer);
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.createMarshaller(), obj, part, writer);
//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.createUnmarshaller(), reader, part, 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.createMarshaller(),
new String("TestSOAPMessage"), part, elNode);
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.createUnmarshaller(),
elNode, part, 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.createUnmarshaller(), n, part, 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.createUnmarshaller(), elNode, part, true);
assertNotNull(obj);
assertEquals(StringStruct.class, obj.getClass());
assertEquals("World", ((StringStruct)obj).getArg1());
try {
// unmarshal with schema should raise exception.
Unmarshaller m = context.createUnmarshaller();
m.setSchema(schema);
obj = JAXBEncoderDecoder.unmarshall(m, elNode, part, 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.createUnmarshaller(),
elNode,
null,
true);
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.createMarshaller(), obj, null, writer);
//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 = getMethod("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 = getMethod("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);
}
@RequestWrapper(localName = "testByte",
targetNamespace = "http://apache.org/type_test/doc",
className = "org.apache.type_test.doc.TestByte")
@ResponseWrapper(localName = "testByteResponse",
targetNamespace = "http://apache.org/type_test/doc",
className = "org.apache.type_test.doc.TestByteResponse")
public byte testByte(
byte x,
javax.xml.ws.Holder<java.lang.Byte> y,
javax.xml.ws.Holder<java.lang.Byte> z) {
return 24;
}
@RequestWrapper(localName = "testBase64Binary",
targetNamespace = "http://apache.org/type_test/doc",
className = "org.apache.type_test.doc.TestBase64Binary")
@ResponseWrapper(localName = "testBase64BinaryResponse",
targetNamespace = "http://apache.org/type_test/doc",
className = "org.apache.type_test.doc.TestBase64BinaryResponse")
public byte[] testBase64Binary(
byte[] x,
javax.xml.ws.Holder<byte[]> y,
javax.xml.ws.Holder<byte[]> z) {
return null;
}
}