Skip to content

Commit

Permalink
Merge 9af6a4e into 80698ed
Browse files Browse the repository at this point in the history
  • Loading branch information
yasserzamani committed Dec 6, 2017
2 parents 80698ed + 9af6a4e commit b79f714
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -180,14 +180,14 @@ public interface ActionInvocation extends Serializable {

/**
* Prepares instance of ActionInvocation to be serializable,
* which simple means removing all unserializable fields, eg. Container
* which simply means removing all unserializable but restorable references
*
* @return ActionInvocation which can be serialize (eg. into HttpSession)
*/
ActionInvocation serialize();

/**
* Performs opposite process to restore back ActionInvocation after deserialisation
* Performs opposite process to restore back ActionInvocation after serialisation
*
* @param actionContext current {@link ActionContext}
* @return fully operational ActionInvocation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
Expand Down Expand Up @@ -501,24 +503,57 @@ protected String saveResult(ActionConfig actionConfig, Object methodResult) {
}

/**
* Version ready to be serialize
* Version ready to be serialize via removing all unserializable but restorable references
*
* @return instance without reference to {@link Container}
* @return instance without unserializable references
*/
public ActionInvocation serialize() {
DefaultActionInvocation that = this;
that.container = null;

if(that.getInvocationContext() != null && that.getInvocationContext().getContextMap() != null) {
Map<String, Object> thatContextMap = that.getInvocationContext().getContextMap();
List<String> keysToRemove = new ArrayList<>();
for (Map.Entry<String, Object> entry : thatContextMap.entrySet()) {
Object entryValue = entry.getValue();
// WW-4873 Remove Servlet Request and Response as they are not intended to being serializable
if (entryValue instanceof ServletRequest ||
entryValue instanceof ServletResponse) {
keysToRemove.add(entry.getKey());
}
}
for (String keyToRemove : keysToRemove) {
thatContextMap.remove(keyToRemove);
}
}

return that;
}

/**
* Restoring Container
* Restoring references
*
* @param actionContext current {@link ActionContext}
* @return instance which can be used to invoke action
*/
public ActionInvocation deserialize(ActionContext actionContext) {
DefaultActionInvocation that = this;

if(that.getInvocationContext() != null && that.getInvocationContext().getContextMap() != null) {
Map<String, Object> thatContextMap = that.getInvocationContext().getContextMap();
Map<String, Object> acContextMap = actionContext.getContextMap();
for (Map.Entry<String, Object> entry : acContextMap.entrySet()) {
Object entryValue = entry.getValue();
String entryKey = entry.getKey();
// WW-4873 Restore Servlet Request and Response
if ((entryValue instanceof ServletRequest ||
entryValue instanceof ServletResponse) &&
!thatContextMap.containsKey(entryKey)) {
thatContextMap.put(entryKey, entryValue);
}
}
}

that.container = actionContext.getContainer();
return that;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ public class BackgroundProcess implements Serializable {
private static final long serialVersionUID = 3884464776311686443L;

protected Object action;
protected ActionInvocation invocation;
protected String result;
protected Exception exception;
protected boolean done;
Expand All @@ -45,13 +44,12 @@ public class BackgroundProcess implements Serializable {
* @param threadPriority The thread priority
*/
public BackgroundProcess(String threadName, final ActionInvocation invocation, int threadPriority) {
this.invocation = invocation;
this.action = invocation.getAction();
try {
final Thread t = new Thread(new Runnable() {
public void run() {
try {
beforeInvocation();
beforeInvocation(invocation);
result = invocation.invokeActionOnly();
afterInvocation();
} catch (Exception e) {
Expand All @@ -75,7 +73,7 @@ public void run() {
*
* @throws Exception any exception thrown will be thrown, in turn, by the ExecuteAndWaitInterceptor
*/
protected void beforeInvocation() throws Exception {
protected void beforeInvocation(ActionInvocation invocation) throws Exception {
ActionContext.setContext(invocation.getInvocationContext());
}

Expand All @@ -99,15 +97,6 @@ public Object getAction() {
return action;
}

/**
* Retrieves the action invocation.
*
* @return the action invocation
*/
public ActionInvocation getInvocation() {
return invocation;
}

/**
* Gets the result of the background process.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import org.apache.struts2.util.TokenHelper;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
Expand Down Expand Up @@ -117,7 +116,6 @@ protected String handleInvalidToken(ActionInvocation invocation) throws Exceptio
ActionContext ac = invocation.getInvocationContext();

HttpServletRequest request = (HttpServletRequest) ac.get(ServletActionContext.HTTP_REQUEST);
HttpServletResponse response = (HttpServletResponse) ac.get(ServletActionContext.HTTP_RESPONSE);
String tokenName = TokenHelper.getTokenName();
String token = TokenHelper.getToken(tokenName);

Expand All @@ -134,9 +132,6 @@ protected String handleInvalidToken(ActionInvocation invocation) throws Exceptio
ValueStack stack = savedInvocation.getStack();
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);

ActionContext savedContext = savedInvocation.getInvocationContext();
savedContext.getContextMap().put(ServletActionContext.HTTP_REQUEST, request);
savedContext.getContextMap().put(ServletActionContext.HTTP_RESPONSE, response);
Result result = savedInvocation.getResult();

if ((result != null) && (savedInvocation.getProxy().getExecuteResult())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,15 @@
import com.opensymphony.xwork2.mock.MockActionProxy;
import com.opensymphony.xwork2.mock.MockContainer;
import com.opensymphony.xwork2.mock.MockInterceptor;
import com.opensymphony.xwork2.mock.MockLazyInterceptor;
import com.opensymphony.xwork2.ognl.OgnlUtil;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.ValueStackFactory;
import org.apache.struts2.dispatcher.HttpParameters;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
Expand All @@ -44,6 +47,8 @@
* @author <a href="mailto:kristian at zenior.no">Kristian Rosenvold</a>
*/
public class DefaultActionInvocationTest extends XWorkTestCase {
private static final String HTTP_REQUEST = "com.opensymphony.xwork2.DefaultActionInvocationTest.HttpServletRequest";
private static final String HTTP_RESPONSE = "com.opensymphony.xwork2.DefaultActionInvocationTest.HttpServletResponse";

/**
* Tests interceptor chain invoke.
Expand Down Expand Up @@ -77,30 +82,74 @@ public void testInvoke() throws Exception {

public void testSerialization() throws Exception {
// given
DefaultActionInvocation actionInvocation = new DefaultActionInvocation(new HashMap<String, Object>(), false);
HashMap<String, Object> extraContext = new HashMap<String, Object>();
DefaultActionInvocation actionInvocation = new DefaultActionInvocation(extraContext, false);
actionInvocation.setContainer(new MockContainer());

extraContext.put(HTTP_REQUEST, new MockHttpServletRequest());
extraContext.put(HTTP_RESPONSE, new MockHttpServletResponse());
actionInvocation.invocationContext = new ActionContext(extraContext);

// when
DefaultActionInvocation serializable = (DefaultActionInvocation) actionInvocation.serialize();

// then
assertNull(actionInvocation.container);
assertNull(serializable.container);

assertFalse("request should be removed from actionInvocation",
actionInvocation.invocationContext.getContextMap().containsKey(HTTP_REQUEST));
assertFalse("response should be removed from actionInvocation",
actionInvocation.invocationContext.getContextMap().containsKey(HTTP_RESPONSE));
assertFalse("request should be removed from serializable",
serializable.invocationContext.getContextMap().containsKey(HTTP_REQUEST));
assertFalse("response should be removed from serializable",
serializable.invocationContext.getContextMap().containsKey(HTTP_RESPONSE));

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(serializable);
oos.close();
assertTrue("should have serialized data", baos.size() > 0);
baos.close();
}

public void testDeserialization() throws Exception {
// given
DefaultActionInvocation actionInvocation = new DefaultActionInvocation(new HashMap<String, Object>(), false);
HashMap<String, Object> extraContext = new HashMap<String, Object>();
DefaultActionInvocation actionInvocation = new DefaultActionInvocation(extraContext, false);
actionInvocation.invocationContext = new ActionContext(extraContext);

MockContainer mockContainer = new MockContainer();
ActionContext.getContext().setContainer(mockContainer);

Map<String, Object> acContextMap = ActionContext.getContext().getContextMap();
MockHttpServletRequest request = new MockHttpServletRequest();
acContextMap.put(HTTP_REQUEST, request);
MockHttpServletResponse response = new MockHttpServletResponse();
acContextMap.put(HTTP_RESPONSE, response);

// when
DefaultActionInvocation deserializable = (DefaultActionInvocation) actionInvocation.deserialize(ActionContext.getContext());

// then
assertNotNull(actionInvocation.container);
assertNotNull(deserializable.container);
assertEquals(mockContainer, deserializable.container);

assertTrue("request should be restored into actionInvocation",
actionInvocation.invocationContext.getContextMap().containsKey(HTTP_REQUEST));
assertTrue("response should be restored into actionInvocation",
actionInvocation.invocationContext.getContextMap().containsKey(HTTP_RESPONSE));
assertTrue("request should be restored into deserializable",
deserializable.invocationContext.getContextMap().containsKey(HTTP_REQUEST));
assertTrue("response should be restored into deserializable",
deserializable.invocationContext.getContextMap().containsKey(HTTP_RESPONSE));

assertEquals(request, actionInvocation.invocationContext.getContextMap().get(HTTP_REQUEST));
assertEquals(response, actionInvocation.invocationContext.getContextMap().get(HTTP_RESPONSE));
assertEquals(request, deserializable.invocationContext.getContextMap().get(HTTP_REQUEST));
assertEquals(response, deserializable.invocationContext.getContextMap().get(HTTP_RESPONSE));
}

public void testInvokingExistingExecuteMethod() throws Exception {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* 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.interceptor;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.mock.MockActionInvocation;
import org.apache.struts2.StrutsInternalTestCase;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;

/**
* Test case for BackgroundProcessTest.
*/
public class BackgroundProcessTest extends StrutsInternalTestCase {

public void testIsSerializable() throws Exception {
MockActionInvocation invocation = new MockActionInvocation();
invocation.setResultCode("BackgroundProcessTest.testIsSerializable");
invocation.setInvocationContext(ActionContext.getContext());

BackgroundProcess bp = new BackgroundProcess("BackgroundProcessTest.testIsSerializable", invocation
, Thread.MIN_PRIORITY);

bp.exception = new Exception();
bp.done = true;

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(bp);
oos.close();
assertTrue("should have serialized data", baos.size() > 0);
baos.close();
}
}

0 comments on commit b79f714

Please sign in to comment.