| /* |
| * 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.struts2.json; |
| |
| import java.util.Calendar; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.struts2.StrutsStatics; |
| import org.apache.struts2.StrutsTestCase; |
| import org.apache.struts2.util.TestUtils; |
| import org.springframework.mock.web.MockHttpServletRequest; |
| import org.springframework.mock.web.MockHttpServletResponse; |
| import org.springframework.mock.web.MockServletContext; |
| |
| import com.opensymphony.xwork2.ActionContext; |
| import com.opensymphony.xwork2.mock.MockActionInvocation; |
| import com.opensymphony.xwork2.util.ValueStack; |
| |
| public class JSONInterceptorTest extends StrutsTestCase { |
| private MockActionInvocationEx invocation; |
| private MockHttpServletRequest request; |
| private MockHttpServletResponse response; |
| |
| private void setRequestContent(String fileName) throws Exception { |
| String content = TestUtils.readContent(JSONInterceptorTest.class.getResource(fileName)); |
| this.request.setContent(content.getBytes()); |
| } |
| |
| public void testBadJSON1() throws Exception { |
| tryBadJSON("bad-1.txt"); |
| } |
| |
| public void testBadJSON2() throws Exception { |
| tryBadJSON("bad-2.txt"); |
| } |
| |
| public void testBadJSON3() throws Exception { |
| tryBadJSON("bad-3.txt"); |
| } |
| |
| public void testBadJSON4() throws Exception { |
| tryBadJSON("bad-4.txt"); |
| } |
| |
| public void testBadJSON5() throws Exception { |
| tryBadJSON("bad-5.txt"); |
| } |
| |
| public void testBadToTheBoneJSON4() throws Exception { |
| tryBadJSON("bad-to-the-bone.txt"); |
| } |
| |
| private void tryBadJSON(String fileName) throws Exception { |
| // request |
| setRequestContent(fileName); |
| this.request.addHeader("Content-Type", "application/json; charset=UTF-8"); |
| |
| JSONInterceptor interceptor = new JSONInterceptor(); |
| interceptor.setEnableSMD(true); |
| SMDActionTest1 action = new SMDActionTest1(); |
| |
| this.invocation.setAction(action); |
| |
| // JSON is not well formed, throw exception |
| try { |
| interceptor.intercept(this.invocation); |
| fail("Should have thrown an exception"); |
| } catch (JSONException e) { |
| // I can't get JUnit to ignore the exception |
| // @Test(expected = JSONException.class) |
| } |
| } |
| |
| public void testSMDDisabledSMD() throws Exception { |
| // request |
| setRequestContent("smd-3.txt"); |
| this.request.addHeader("Content-Type", "application/json-rpc"); |
| |
| JSONInterceptor interceptor = new JSONInterceptor(); |
| SMDActionTest1 action = new SMDActionTest1(); |
| |
| this.invocation.setAction(action); |
| |
| // SMD was not enabled so invocation must happen |
| try { |
| interceptor.intercept(this.invocation); |
| } catch (JSONException e) { |
| fail("Should have not thrown an exception"); |
| } |
| |
| } |
| |
| public void testSMDAliasedMethodCall1() throws Exception { |
| // request |
| setRequestContent("smd-14.txt"); |
| this.request.addHeader("Content-Type", "application/json-rpc"); |
| |
| JSONInterceptor interceptor = new JSONInterceptor(); |
| interceptor.setEnableSMD(true); |
| SMDActionTest2 action = new SMDActionTest2(); |
| |
| this.invocation.setAction(action); |
| |
| interceptor.intercept(this.invocation); |
| // method was aliased, but was invoked with the regular name |
| // so method must not be invoked |
| assertFalse(this.invocation.isInvoked()); |
| assertFalse(action.isDoSomethingInvoked()); |
| } |
| |
| public void testSMDAliasedMethodCall2() throws Exception { |
| // request |
| setRequestContent("smd-15.txt"); |
| this.request.addHeader("Content-Type", "application/json-rpc"); |
| |
| JSONInterceptor interceptor = new JSONInterceptor(); |
| interceptor.setEnableSMD(true); |
| SMDActionTest2 action = new SMDActionTest2(); |
| |
| this.invocation.setAction(action); |
| |
| interceptor.intercept(this.invocation); |
| // method was aliased, but was invoked with the aliased name |
| // so method must be invoked |
| assertFalse(this.invocation.isInvoked()); |
| assertTrue(action.isDoSomethingInvoked()); |
| } |
| |
| public void testSMDNoMethod() throws Exception { |
| // request |
| setRequestContent("smd-4.txt"); |
| this.request.addHeader("Content-Type", "application/json-rpc"); |
| |
| JSONInterceptor interceptor = new JSONInterceptor(); |
| interceptor.setEnableSMD(true); |
| SMDActionTest1 action = new SMDActionTest1(); |
| |
| this.invocation.setAction(action); |
| |
| // SMD was enabled so invocation must happen |
| |
| interceptor.intercept(this.invocation); |
| |
| String json = response.getContentAsString(); |
| |
| String normalizedActual = TestUtils.normalize(json, true); |
| String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("smd-13.txt")); |
| assertEquals(normalizedExpected, normalizedActual); |
| |
| assertFalse(this.invocation.isInvoked()); |
| } |
| |
| public void testSMDMethodWithoutAnnotations() throws Exception { |
| // request |
| setRequestContent("smd-9.txt"); |
| this.request.addHeader("Content-Type", "application/json-rpc"); |
| |
| JSONInterceptor interceptor = new JSONInterceptor(); |
| interceptor.setEnableSMD(true); |
| SMDActionTest1 action = new SMDActionTest1(); |
| |
| this.invocation.setAction(action); |
| |
| // SMD was enabled so invocation must happen |
| try { |
| interceptor.intercept(this.invocation); |
| assertTrue("Exception was expected here!", true); |
| } catch (Exception e) { |
| // ok |
| } |
| assertFalse(this.invocation.isInvoked()); |
| } |
| |
| public void testSMDPrimitivesNoResult() throws Exception { |
| // request |
| setRequestContent("smd-6.txt"); |
| this.request.addHeader("Content-Type", "application/json-rpc"); |
| |
| JSONInterceptor interceptor = new JSONInterceptor(); |
| interceptor.setEnableSMD(true); |
| SMDActionTest1 action = new SMDActionTest1(); |
| |
| this.invocation.setAction(action); |
| |
| // can't be invoked |
| interceptor.intercept(this.invocation); |
| assertFalse(this.invocation.isInvoked()); |
| |
| // asert values were passed properly |
| assertEquals("string", action.getStringParam()); |
| assertEquals(1, action.getIntParam()); |
| assertEquals(true, action.isBooleanParam()); |
| assertEquals('c', action.getCharParam()); |
| assertEquals(2, action.getLongParam()); |
| assertEquals(new Float(3.3), action.getFloatParam()); |
| assertEquals(4.4, action.getDoubleParam()); |
| assertEquals(5, action.getShortParam()); |
| assertEquals(6, action.getByteParam()); |
| |
| String json = response.getContentAsString(); |
| |
| String normalizedActual = TestUtils.normalize(json, true); |
| String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("smd-11.txt")); |
| assertEquals(normalizedExpected, normalizedActual); |
| |
| assertEquals("application/json;charset=UTF-8", response.getContentType()); |
| } |
| |
| public void testSMDReturnObject() throws Exception { |
| // request |
| setRequestContent("smd-10.txt"); |
| this.request.addHeader("Content-Type", "application/json-rpc"); |
| |
| JSONInterceptor interceptor = new JSONInterceptor(); |
| interceptor.setEnableSMD(true); |
| SMDActionTest2 action = new SMDActionTest2(); |
| |
| this.invocation.setAction(action); |
| |
| // can't be invoked |
| interceptor.intercept(this.invocation); |
| assertFalse(this.invocation.isInvoked()); |
| |
| String json = response.getContentAsString(); |
| |
| String normalizedActual = TestUtils.normalize(json, true); |
| String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("smd-12.txt")); |
| assertEquals(normalizedExpected, normalizedActual); |
| |
| assertEquals("application/json;charset=UTF-8", response.getContentType()); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public void testSMDObjectsNoResult() throws Exception { |
| // request |
| setRequestContent("smd-7.txt"); |
| this.request.addHeader("Content-Type", "application/json-rpc"); |
| |
| JSONInterceptor interceptor = new JSONInterceptor(); |
| interceptor.setEnableSMD(true); |
| SMDActionTest1 action = new SMDActionTest1(); |
| |
| this.invocation.setAction(action); |
| |
| // can't be invoked |
| interceptor.intercept(this.invocation); |
| assertFalse(this.invocation.isInvoked()); |
| |
| // asert values were passed properly |
| Bean bean = action.getBeanParam(); |
| assertNotNull(bean); |
| assertTrue(bean.isBooleanField()); |
| assertEquals(bean.getStringField(), "test"); |
| assertEquals(bean.getIntField(), 10); |
| assertEquals(bean.getCharField(), 's'); |
| assertEquals(bean.getDoubleField(), 10.1); |
| assertEquals(bean.getByteField(), 3); |
| |
| List list = action.getListParam(); |
| assertNotNull(list); |
| assertEquals("str0", list.get(0)); |
| assertEquals("str1", list.get(1)); |
| |
| Map map = action.getMapParam(); |
| assertNotNull(map); |
| assertNotNull(map.get("a")); |
| assertEquals(new Long(1), map.get("a")); |
| assertNotNull(map.get("c")); |
| List insideList = (List) map.get("c"); |
| assertEquals(1.0d, insideList.get(0)); |
| assertEquals(2.0d, insideList.get(1)); |
| |
| String json = response.getContentAsString(); |
| String normalizedActual = TestUtils.normalize(json, true); |
| String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("smd-11.txt")); |
| assertEquals(normalizedExpected, normalizedActual); |
| |
| assertEquals("application/json;charset=UTF-8", response.getContentType()); |
| } |
| |
| @SuppressWarnings( { "unchecked", "unchecked" }) |
| public void testReadEmpty() throws Exception { |
| // request |
| setRequestContent("json-6.txt"); |
| this.request.addHeader("Content-Type", "application/json"); |
| |
| // interceptor |
| JSONInterceptor interceptor = new JSONInterceptor(); |
| TestAction action = new TestAction(); |
| |
| this.invocation.setAction(action); |
| |
| interceptor.intercept(this.invocation); |
| } |
| |
| @SuppressWarnings( { "unchecked", "unchecked" }) |
| public void test() throws Exception { |
| // request |
| setRequestContent("json-1.txt"); |
| this.request.addHeader("Content-Type", "application/json"); |
| |
| // interceptor |
| JSONInterceptor interceptor = new JSONInterceptor(); |
| TestAction action = new TestAction(); |
| |
| this.invocation.setAction(action); |
| this.invocation.getStack().push(action); |
| |
| interceptor.intercept(this.invocation); |
| |
| // serialize and compare |
| List list = action.getList(); |
| |
| assertNotNull(list); |
| assertEquals(list.size(), 10); |
| |
| list = action.getCollection(); |
| assertNotNull(list); |
| assertEquals(list.size(), 3); |
| assertEquals(list.get(0), "b"); |
| assertEquals(list.get(1), 1L); |
| list = (List) list.get(2); |
| assertNotNull(list); |
| assertEquals(list.size(), 2); |
| assertEquals(list.get(0), 10L); |
| assertEquals(list.get(1), 12L); |
| |
| list = action.getCollection2(); |
| assertNotNull(list); |
| assertEquals(list.size(), 1); |
| |
| // inside a map any primitive is either: String, Long, Boolean or Double |
| Map bean = (Map) list.get(0); |
| |
| assertNotNull(bean); |
| assertTrue((Boolean) bean.get("booleanField")); |
| assertEquals(bean.get("charField"), "s"); |
| assertEquals(bean.get("doubleField"), 10.1); |
| assertEquals(bean.get("floatField"), 1.5); |
| assertEquals(bean.get("intField"), 10L); |
| assertEquals(bean.get("longField"), 100L); |
| assertEquals(bean.get("stringField"), "str"); |
| |
| bean = (Map) bean.get("objectField"); |
| assertNotNull(bean); |
| assertFalse((Boolean) bean.get("booleanField")); |
| assertEquals(bean.get("charField"), "\u0000"); |
| assertEquals(bean.get("doubleField"), 2.2); |
| assertEquals(bean.get("floatField"), 1.1); |
| assertEquals(bean.get("intField"), 0L); |
| assertEquals(bean.get("longField"), 0L); |
| assertEquals(bean.get("stringField"), " "); |
| |
| assertEquals(action.getFoo(), "foo"); |
| |
| Map map = action.getMap(); |
| |
| assertNotNull(map); |
| assertEquals(map.size(), 2); |
| assertEquals(map.get("a"), 1L); |
| list = (List) map.get("c"); |
| assertNotNull(list); |
| assertEquals(list.size(), 2); |
| assertEquals(list.get(0), 1.0); |
| assertEquals(list.get(1), 2.0); |
| |
| assertEquals(action.getResult(), null); |
| |
| Bean bean2 = action.getBean(); |
| |
| assertNotNull(bean2); |
| assertTrue(bean2.isBooleanField()); |
| assertEquals(bean2.getStringField(), "test"); |
| assertEquals(bean2.getIntField(), 10); |
| assertEquals(bean2.getCharField(), 's'); |
| assertEquals(bean2.getDoubleField(), 10.1); |
| assertEquals(bean2.getByteField(), 3); |
| |
| String[] strArray = action.getArray(); |
| |
| assertNotNull(strArray); |
| assertEquals(strArray.length, 2); |
| assertEquals(strArray[0], "str0"); |
| assertEquals(strArray[1], "str1"); |
| |
| int[] intArray = action.getIntArray(); |
| |
| assertNotNull(intArray); |
| assertEquals(intArray.length, 2); |
| assertEquals(intArray[0], 1); |
| assertEquals(intArray[1], 2); |
| |
| Bean[] beanArray = action.getBeanArray(); |
| |
| assertNotNull(beanArray); |
| assertNotNull(beanArray[0]); |
| assertEquals(beanArray[0].getStringField(), "bean1"); |
| assertNotNull(beanArray[1]); |
| assertEquals(beanArray[1].getStringField(), "bean2"); |
| |
| Calendar calendar = Calendar.getInstance(); |
| calendar.setTime(action.getDate()); |
| |
| assertEquals(calendar.get(Calendar.YEAR), 1999); |
| assertEquals(calendar.get(Calendar.MONTH), Calendar.DECEMBER); |
| assertEquals(calendar.get(Calendar.DAY_OF_MONTH), 31); |
| assertEquals(calendar.get(Calendar.HOUR), 11); |
| assertEquals(calendar.get(Calendar.MINUTE), 59); |
| assertEquals(calendar.get(Calendar.SECOND), 59); |
| |
| calendar.setTime(action.getDate2()); |
| assertEquals(calendar.get(Calendar.YEAR), 1999); |
| assertEquals(calendar.get(Calendar.MONTH), Calendar.DECEMBER); |
| assertEquals(calendar.get(Calendar.DAY_OF_MONTH), 31); |
| |
| // test desrialize=false |
| assertNull(action.getFoo2()); |
| } |
| |
| public void testRoot() throws Exception { |
| setRequestContent("json-5.txt"); |
| this.request.addHeader("Content-Type", "application/json"); |
| |
| // interceptor |
| JSONInterceptor interceptor = new JSONInterceptor(); |
| interceptor.setRoot("bean"); |
| TestAction4 action = new TestAction4(); |
| |
| this.invocation.setAction(action); |
| this.invocation.getStack().push(action); |
| |
| interceptor.intercept(this.invocation); |
| |
| Bean bean2 = action.getBean(); |
| |
| assertNotNull(bean2); |
| assertTrue(bean2.isBooleanField()); |
| assertEquals(bean2.getStringField(), "test"); |
| assertEquals(bean2.getIntField(), 10); |
| assertEquals(bean2.getCharField(), 's'); |
| assertEquals(bean2.getDoubleField(), 10.1); |
| assertEquals(bean2.getByteField(), 3); |
| } |
| |
| public void testJSONArray() throws Exception { |
| setRequestContent("json-12.txt"); |
| this.request.addHeader("Content-Type", "application/json"); |
| |
| // interceptor |
| JSONInterceptor interceptor = new JSONInterceptor(); |
| interceptor.setRoot("beans"); |
| TestAction5 action = new TestAction5(); |
| |
| this.invocation.setAction(action); |
| this.invocation.getStack().push(action); |
| |
| interceptor.intercept(this.invocation); |
| |
| List<Bean> beans = action.getBeans(); |
| |
| assertNotNull(beans); |
| assertEquals(1, beans.size()); |
| assertTrue(beans.get(0).isBooleanField()); |
| assertEquals(beans.get(0).getStringField(), "test"); |
| assertEquals(beans.get(0).getIntField(), 10); |
| assertEquals(beans.get(0).getCharField(), 's'); |
| assertEquals(beans.get(0).getDoubleField(), 10.1); |
| assertEquals(beans.get(0).getByteField(), 3); |
| } |
| |
| public void testJSONArray2() throws Exception { |
| setRequestContent("json-12.txt"); |
| this.request.addHeader("Content-Type", "application/json"); |
| |
| // interceptor |
| JSONInterceptor interceptor = new JSONInterceptor(); |
| interceptor.setRoot("anotherBean.yetAnotherBean.beans"); |
| TestAction5 action = new TestAction5(); |
| |
| this.invocation.setAction(action); |
| this.invocation.getStack().push(action); |
| |
| interceptor.intercept(this.invocation); |
| |
| List<Bean> beans = action.getAnotherBean().getYetAnotherBean().getBeans(); |
| |
| assertNotNull(beans); |
| assertEquals(1, beans.size()); |
| assertTrue(beans.get(0).isBooleanField()); |
| assertEquals(beans.get(0).getStringField(), "test"); |
| assertEquals(beans.get(0).getIntField(), 10); |
| assertEquals(beans.get(0).getCharField(), 's'); |
| assertEquals(beans.get(0).getDoubleField(), 10.1); |
| assertEquals(beans.get(0).getByteField(), 3); |
| } |
| |
| @Override |
| protected void setUp() throws Exception { |
| super.setUp(); |
| |
| this.request = new MockHttpServletRequest(); |
| this.response = new MockHttpServletResponse(); |
| |
| ActionContext context = ActionContext.getContext(); |
| ValueStack stack = context.getValueStack(); |
| |
| ActionContext.setContext(context); |
| context.put(StrutsStatics.HTTP_REQUEST, this.request); |
| context.put(StrutsStatics.HTTP_RESPONSE, this.response); |
| |
| MockServletContext servletContext = new MockServletContext(); |
| |
| context.put(StrutsStatics.SERVLET_CONTEXT, servletContext); |
| this.invocation = new MockActionInvocationEx(); |
| this.invocation.setInvocationContext(context); |
| this.invocation.setStack(stack); |
| } |
| } |
| |
| class MockActionInvocationEx extends MockActionInvocation { |
| |
| private boolean invoked; |
| |
| @Override |
| public String invoke() throws Exception { |
| this.invoked = true; |
| return super.invoke(); |
| } |
| |
| public boolean isInvoked() { |
| return this.invoked; |
| } |
| |
| public void setInvoked(boolean invoked) { |
| this.invoked = invoked; |
| } |
| |
| } |