Package org.apache.wink.common.internal.providers.jaxb

Source Code of org.apache.wink.common.internal.providers.jaxb.ProvidersJAXBTest$MyJAXBXmlProvider

/*******************************************************************************
* 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.wink.common.internal.providers.jaxb;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.StringTokenizer;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Providers;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLStreamException;
import javax.xml.transform.stream.StreamSource;

import org.apache.wink.common.RuntimeContext;
import org.apache.wink.common.internal.CaseInsensitiveMultivaluedMap;
import org.apache.wink.common.internal.WinkConfiguration;
import org.apache.wink.common.internal.contexts.MediaTypeCharsetAdjuster;
import org.apache.wink.common.internal.providers.entity.xml.JAXBXmlProvider;
import org.apache.wink.common.internal.providers.jaxb.jaxb1.AddNumbers;
import org.apache.wink.common.internal.providers.jaxb.jaxb1.MyPojo;
import org.apache.wink.common.internal.runtime.RuntimeContextTLS;
import org.apache.wink.common.model.JAXBUnmarshalOptions;
import org.apache.wink.common.model.XmlFormattingOptions;
import org.jmock.Expectations;
import org.jmock.integration.junit3.MockObjectTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class ProvidersJAXBTest extends MockObjectTestCase {
   
    public class MyJAXBXmlProvider extends JAXBXmlProvider {

        MyJAXBXmlProvider() {
            super();
            providers = ProvidersJAXBTest.this.providers;
        }
       
        /*
         * simulate what would happen if application had supplied a JAXBContext provider
         */
        @Override
        protected JAXBContext getContext(Class<?> type, MediaType mediaType)
                throws JAXBException {
            // use JAXBContext.newInstance(String).  The default in AbstractJAXBProvider is JAXBContext.newInstance(Class)
            return JAXBContext.newInstance(type.getPackage().getName());
        }
       
    }
   
    static final String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +
        "<ns2:addNumbers xmlns:ns2=\"http://org/apache/wink/common/internal/providers/jaxb/jaxb1\">" +
        "<ns2:arg0>1</ns2:arg0>" +
        "<ns2:arg1>2</ns2:arg1>" +
        "</ns2:addNumbers>";
   
    static final String expectedXml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +
        "<addNumbers xmlns=\"http://org/apache/wink/common/internal/providers/jaxb/jaxb1\">" +
        "<arg0>0</arg0>" +
        "<arg1>0</arg1>" +
        "</addNumbers>";

    static String path = null;
    static {
        String classpath = System.getProperty("java.class.path");
        StringTokenizer tokenizer = new StringTokenizer(classpath, System.getProperty("path.separator"));
        while (tokenizer.hasMoreTokens()) {
            path = tokenizer.nextToken();
            if (path.endsWith("test-classes")) {
                break;
            }
        }
        // for windows:
        int driveIndex = path.indexOf(":");
        if(driveIndex != -1) {
            path = path.substring(driveIndex + 1);
        }

    }
   
    static final String xmlWithDTD = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +
        "<!DOCTYPE data [<!ENTITY file SYSTEM \"file:"+ path + "/etc/ProvidersJAXBTest.txt\">]>" +
        "<ns2:addNumbers xmlns:ns2=\"http://org/apache/wink/common/internal/providers/jaxb/jaxb1\">" +
        "<ns2:arg0>&file;</ns2:arg0>" +
        "<ns2:arg1>2</ns2:arg1>" +
        "</ns2:addNumbers>";
   
    static final String xmlMyPojoWithDTD = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +
        "<!DOCTYPE data [<!ENTITY file SYSTEM \"file:"+ path +"/etc/ProvidersJAXBTest.txt\">]>" +
        "<ns2:myPojo xmlns:ns2=\"http://org/apache/wink/common/internal/providers/jaxb/jaxb1\">" +
        "<ns2:stringdata>&file;</ns2:stringdata>" +
        "</ns2:myPojo>";
   
    static final String xmlWithDTDEntityExpansionAttack = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +
        "<!DOCTYPE root [" +
        "<!ENTITY % a \"x\">" +
        "<!ENTITY % b \"%a;%a;\">" +
        "]>" +
        "<ns2:addNumbers xmlns:ns2=\"http://org/apache/wink/common/internal/providers/jaxb/jaxb1\">" +
        "<ns2:arg0>&b;</ns2:arg0>" +
        "<ns2:arg1>2</ns2:arg1>" +
        "</ns2:addNumbers>";
   
    static final String xmlWithDTDEntityExpansionAttack2 = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +
        "<!DOCTYPE root [" +
        "<!ENTITY x32 \"foobar\">" +
        "<!ENTITY x31 \"&x32;&x32;\">" +
        "<!ENTITY x30 \"&x31;&x31;\">" +
        "<!ENTITY x29 \"&x30;&x30;\">" +
        "<!ENTITY x28 \"&x29;&x29;\">" +
        "<!ENTITY x27 \"&x28;&x28;\">" +
        "<!ENTITY x26 \"&x27;&x27;\">" +
        "<!ENTITY x25 \"&x26;&x26;\">" +
        "<!ENTITY x24 \"&x25;&x25;\">" +
        "<!ENTITY x23 \"&x24;&x24;\">" +
        "<!ENTITY x22 \"&x23;&x23;\">" +
        "<!ENTITY x21 \"&x22;&x22;\">" +
        "<!ENTITY x20 \"&x21;&x21;\">" +
        "<!ENTITY x19 \"&x20;&x20;\">" +
        "<!ENTITY x18 \"&x19;&x19;\">" +
        "<!ENTITY x17 \"&x18;&x18;\">" +
        "<!ENTITY x16 \"&x17;&x17;\">" +
        "<!ENTITY x15 \"&x16;&x16;\">" +
        "<!ENTITY x14 \"&x15;&x15;\">" +
        "<!ENTITY x13 \"&x14;&x14;\">" +
        "<!ENTITY x12 \"&x13;&x13;\">" +
        "<!ENTITY x11 \"&x12;&x12;\">" +
        "<!ENTITY x10 \"&x11;&x11;\">" +
        "<!ENTITY  x9 \"&x10;&x10;\">" +
        "<!ENTITY  x8 \"&x9;&x9;\">" +
        "<!ENTITY  x7 \"&x8;&x8;\">" +
        "<!ENTITY  x6 \"&x7;&x7;\">" +
        "<!ENTITY  x5 \"&x6;&x6;\">" +
        "<!ENTITY  x4 \"&x5;&x5;\">" +
        "<!ENTITY  x3 \"&x4;&x4;\">" +
        "<!ENTITY  x2 \"&x3;&x3;\">" +
        "<!ENTITY  x1 \"&x2;&x2;\">" +
        "]>" +
        "<ns2:addNumbers xmlns:ns2=\"http://org/apache/wink/common/internal/providers/jaxb/jaxb1\">" +
        "<ns2:arg0>&x1;</ns2:arg0>" +
        "<ns2:arg1>2</ns2:arg1>" +
        "</ns2:addNumbers>";


    private WinkConfiguration winkConfiguration = null;
    private MessageBodyReader jaxbProviderReader = null;
    private MessageBodyWriter jaxbProviderWriter = null;
    private Providers providers;
   
    public class MyJAXBContextResolver implements ContextResolver<JAXBContext> {

        public JAXBContext getContext(Class<?> arg0) {
            try {
                return JAXBContext.newInstance(arg0);
            } catch (JAXBException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        }
    }
   
    @Before
    public void setUp() {
        providers = mock(Providers.class);
        final RuntimeContext runtimeContext = mock(RuntimeContext.class);
        winkConfiguration = mock(WinkConfiguration.class);
        checking(new Expectations() {{
            allowing(providers).getContextResolver(JAXBContext.class, MediaType.TEXT_XML_TYPE); will(returnValue(new MyJAXBContextResolver()));
            allowing(providers).getContextResolver(XmlFormattingOptions.class, MediaType.TEXT_XML_TYPE); will(returnValue(null));
            allowing(providers).getContextResolver(JAXBUnmarshalOptions.class, MediaType.TEXT_XML_TYPE); will(returnValue(null));
            allowing(runtimeContext).getAttribute(MediaTypeCharsetAdjuster.class); will(returnValue(null));
            allowing(runtimeContext).getAttribute(WinkConfiguration.class); will(returnValue(winkConfiguration));
        }});
        RuntimeContextTLS.setRuntimeContext(runtimeContext);
        jaxbProviderReader = new MyJAXBXmlProvider();
        jaxbProviderWriter = new MyJAXBXmlProvider();
       
    }
   
    @After
    public void tearDown() {
        // clean up the mess.  :)
        RuntimeContextTLS.setRuntimeContext(null);
    }
   
    @Test
    public void testJAXBUnmarshallingWithAlternateContext1() throws Exception {
       
        final Properties props = new Properties();
        checking(new Expectations() {{
            allowing(winkConfiguration).getProperties(); will(returnValue(props));
        }});
       
        // let's make sure our test string is unmarshallable, just for a good sanity check
        JAXBContext testcontext = JAXBContext.newInstance(AddNumbers.class);
        Unmarshaller testunmarshaller = testcontext.createUnmarshaller();
        AddNumbers testresponse =
            (AddNumbers)testunmarshaller.unmarshal(new ByteArrayInputStream(xml.getBytes()));
        assertEquals("we could not unmarshal the test xml", 1, testresponse.getArg0());
       
        assertTrue(jaxbProviderReader.isReadable(AddNumbers.class, null, null, MediaType.TEXT_XML_TYPE));
        ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes());
        Object obj = jaxbProviderReader.readFrom(AddNumbers.class, null, null, MediaType.TEXT_XML_TYPE, null, bais);
        assertTrue(obj instanceof AddNumbers);
        assertEquals(1, ((AddNumbers)obj).getArg0());
        assertEquals(2, ((AddNumbers)obj).getArg1());
    }
   
    @SuppressWarnings("unchecked")
    @Test
    public void testJAXBMarshalling() throws WebApplicationException, IOException {
        assertTrue(jaxbProviderWriter.isWriteable(AddNumbers.class, null, null, MediaType.TEXT_XML_TYPE));
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        jaxbProviderWriter.writeTo(new AddNumbers(), AddNumbers.class, null, null, MediaType.TEXT_XML_TYPE, null, baos);
        assertEquals(expectedXml, baos.toString());
    }
   
    @SuppressWarnings("unchecked")
    @Test
    public void testJAXBMarshallingWithMap() throws WebApplicationException, IOException {
        assertTrue(jaxbProviderWriter.isWriteable(AddNumbers.class, null, null, MediaType.TEXT_XML_TYPE));
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        MultivaluedMap map = new CaseInsensitiveMultivaluedMap<Object>();
        jaxbProviderWriter.writeTo(new AddNumbers(), AddNumbers.class, null, null, MediaType.TEXT_XML_TYPE, map, baos);
        assertEquals(expectedXml, baos.toString());
    }
   
    @Test
    public void testJAXBUnmarshallingWithDTD() throws Exception {
       
        final Properties props = new Properties();
        checking(new Expectations() {{
            allowing(winkConfiguration).getProperties(); will(returnValue(props));
        }});
       
        Exception ex = null;
        assertTrue(jaxbProviderReader.isReadable(AddNumbers.class, null, null, MediaType.TEXT_XML_TYPE));
        try {
            ByteArrayInputStream bais = new ByteArrayInputStream(xmlWithDTD.getBytes());
            Object obj = jaxbProviderReader.readFrom(AddNumbers.class, null, null, MediaType.TEXT_XML_TYPE, null, bais);
            fail("should have got an exception");
        } catch (Exception e) {
            ex = e;
        }
        assertTrue("expected an XMLStreamException", ex.getCause() instanceof XMLStreamException);
       
        // let's make sure our test string is unmarshallable, just for a good sanity check
        JAXBContext testcontext = JAXBContext.newInstance(AddNumbers.class);
        Unmarshaller testunmarshaller = testcontext.createUnmarshaller();
        AddNumbers testresponse =
            (AddNumbers)testunmarshaller.unmarshal(new ByteArrayInputStream(xmlWithDTD.getBytes()));
        assertEquals("we could not unmarshal the test xml", 99999999, testresponse.getArg0());
    }
   
    @Test
    /**
     * testing that supporting DTD expansion is configurable
     */
    public void testJAXBUnmarshallingWithDTDServerConfigurable() throws Exception {
       
        // pretend we're on the server:
        final Properties props = new Properties();
        props.put("wink.supportDTDEntityExpansion", "true");
        checking(new Expectations() {{
            allowing(winkConfiguration).getProperties(); will(returnValue(props));
        }});
       
        assertTrue(jaxbProviderReader.isReadable(AddNumbers.class, null, null, MediaType.TEXT_XML_TYPE));
        ByteArrayInputStream bais = new ByteArrayInputStream(xmlWithDTD.getBytes());
        Object obj = jaxbProviderReader.readFrom(AddNumbers.class, null, null, MediaType.TEXT_XML_TYPE, null, bais);
        assertTrue(obj instanceof AddNumbers);
        assertEquals(99999999, ((AddNumbers)obj).getArg0());
        assertEquals(2, ((AddNumbers)obj).getArg1());
       
        // let's make sure our test string is unmarshallable, just for a good sanity check
        JAXBContext testcontext = JAXBContext.newInstance(AddNumbers.class);
        Unmarshaller testunmarshaller = testcontext.createUnmarshaller();
        AddNumbers testresponse =
            (AddNumbers)testunmarshaller.unmarshal(new ByteArrayInputStream(xmlWithDTD.getBytes()));
        assertEquals("we could not unmarshal the test xml", 99999999, testresponse.getArg0());
    }
   
    @Test
    public void testJAXBUnmarshallingMyPojoWithDTD() throws Exception {

        final Properties props = new Properties();
        checking(new Expectations() {{
            allowing(winkConfiguration).getProperties(); will(returnValue(props));
        }});
       
        Exception ex = null;
        try {
            assertTrue(jaxbProviderReader.isReadable(MyPojo.class, null, null, MediaType.TEXT_XML_TYPE));
            ByteArrayInputStream bais = new ByteArrayInputStream(xmlMyPojoWithDTD.getBytes());
            Object obj = jaxbProviderReader.readFrom(MyPojo.class, null, null, MediaType.TEXT_XML_TYPE, null, bais);
            fail("should have got an exception");
        } catch (Exception e) {
            ex = e;
        }
        assertTrue("expected an XMLStreamException", ex.getCause() instanceof XMLStreamException);
       
        // let's make sure our test string is unmarshallable, just for a good sanity check
        JAXBContext testcontext = JAXBContext.newInstance(MyPojo.class);
        Unmarshaller testunmarshaller = testcontext.createUnmarshaller();
        JAXBElement<MyPojo> testresponse =
            (JAXBElement<MyPojo>)testunmarshaller.unmarshal(new StreamSource(new ByteArrayInputStream(xmlMyPojoWithDTD.getBytes())), MyPojo.class);
        MyPojo myPojo = testresponse.getValue();
        assertEquals("we could not unmarshal the test xml", "99999999", myPojo.getStringdata().trim());
    }
   
    @Test
    public void testEntityExpansionAttack() throws Exception {
       
        final Properties props = new Properties();
        checking(new Expectations() {{
            allowing(winkConfiguration).getProperties(); will(returnValue(props));
        }});
       
        Exception ex = null;
        try {
            assertTrue(jaxbProviderReader.isReadable(MyPojo.class, null, null, MediaType.TEXT_XML_TYPE));
            ByteArrayInputStream bais = new ByteArrayInputStream(xmlWithDTDEntityExpansionAttack.getBytes());
            Object obj = jaxbProviderReader.readFrom(MyPojo.class, null, null, MediaType.TEXT_XML_TYPE, null, bais);
            fail("should have got an exception");
        } catch (Exception e) {
            ex = e;
        }
        assertTrue("expected an XMLStreamException", ex.getCause() instanceof XMLStreamException);
    }
   
    @Test(timeout=2000)
    public void testEntityExpansionAttack2() throws Exception {
       
        final Properties props = new Properties();
        checking(new Expectations() {{
            allowing(winkConfiguration).getProperties(); will(returnValue(props));
        }});
       
        Exception ex = null;
        try {
            assertTrue(jaxbProviderReader.isReadable(MyPojo.class, null, null, MediaType.TEXT_XML_TYPE));
            ByteArrayInputStream bais = new ByteArrayInputStream(xmlWithDTDEntityExpansionAttack2.getBytes());
            Object obj = jaxbProviderReader.readFrom(MyPojo.class, null, null, MediaType.TEXT_XML_TYPE, null, bais);
            fail("should have got an exception");
        } catch (Exception e) {
            ex = e;
        }
        assertTrue("expected an XMLStreamException", ex.getCause() instanceof XMLStreamException);
    }

}
TOP

Related Classes of org.apache.wink.common.internal.providers.jaxb.ProvidersJAXBTest$MyJAXBXmlProvider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.