package org.apache.myfaces.test.mock; | |
import java.io.ByteArrayInputStream; | |
import java.io.ByteArrayOutputStream; | |
import java.io.IOException; | |
import java.io.ObjectInputStream; | |
import java.io.ObjectOutputStream; | |
import javax.faces.FacesException; | |
import javax.faces.application.StateManager.SerializedView; | |
import javax.faces.context.FacesContext; | |
import javax.faces.context.ResponseWriter; | |
import javax.faces.render.RenderKitFactory; | |
import javax.faces.render.ResponseStateManager; | |
/** | |
* Mock class that encode view state in hex format | |
* | |
* @author lu4242 | |
* | |
*/ | |
public class MockResponseStateManager extends ResponseStateManager | |
{ | |
// ------------------------------------------------------------ Constructors | |
// ------------------------------------------------------ Instance Variables | |
private static final int TREE_PARAM = 0; | |
private static final int STATE_PARAM = 1; | |
private static final int VIEWID_PARAM = 2; | |
private static final String ZIP_CHARSET = "ISO-8859-1"; | |
// ----------------------------------------------------- Mock Object Methods | |
// -------------------------------------------------- ResponseStateManager Methods | |
public Object getState(FacesContext facesContext, String viewId) | |
{ | |
Object[] savedState = getSavedState(facesContext); | |
if (savedState == null) | |
{ | |
return null; | |
} | |
return new Object[] { savedState[TREE_PARAM], savedState[STATE_PARAM] }; | |
} | |
public Object getTreeStructureToRestore(FacesContext facesContext, String viewId) | |
{ | |
// Although this method won't be called anymore, | |
// it has been kept for backward compatibility. | |
Object[] savedState = getSavedState(facesContext); | |
if (savedState == null) | |
{ | |
return null; | |
} | |
return savedState[TREE_PARAM]; | |
} | |
public Object getComponentStateToRestore(FacesContext facesContext) | |
{ | |
// Although this method won't be called anymore, | |
// it has been kept for backward compatibility. | |
Object[] savedState = getSavedState(facesContext); | |
if (savedState == null) | |
{ | |
return null; | |
} | |
return savedState[STATE_PARAM]; | |
} | |
public boolean isPostback(FacesContext context) | |
{ | |
return context.getExternalContext().getRequestParameterMap().containsKey(ResponseStateManager.VIEW_STATE_PARAM); | |
} | |
public void writeState(FacesContext facescontext, SerializedView serializedview) | |
throws IOException | |
{ | |
ResponseWriter responseWriter = facescontext.getResponseWriter(); | |
Object[] savedState = new Object[3]; | |
if (facescontext.getApplication().getStateManager().isSavingStateInClient(facescontext)) | |
{ | |
Object treeStruct = serializedview.getStructure(); | |
Object compStates = serializedview.getState(); | |
if (treeStruct != null) | |
{ | |
savedState[TREE_PARAM] = treeStruct; | |
} | |
if (compStates != null) | |
{ | |
savedState[STATE_PARAM] = compStates; | |
} | |
} | |
else | |
{ | |
// write viewSequence | |
Object treeStruct = serializedview.getStructure(); | |
if (treeStruct != null) | |
{ | |
if (treeStruct instanceof String) | |
{ | |
savedState[TREE_PARAM] = treeStruct; | |
} | |
} | |
} | |
savedState[VIEWID_PARAM] = facescontext.getViewRoot().getViewId(); | |
// write the view state field | |
writeViewStateField(facescontext, responseWriter, savedState); | |
// renderKitId field | |
writeRenderKitIdField(facescontext, responseWriter); | |
} | |
private void writeViewStateField(FacesContext facesContext, ResponseWriter responseWriter, Object savedState) | |
throws IOException | |
{ | |
String serializedState = construct(facesContext, savedState); | |
responseWriter.startElement("input", null); | |
responseWriter.writeAttribute("type", "hidden", null); | |
responseWriter.writeAttribute("name", VIEW_STATE_PARAM, null); | |
responseWriter.writeAttribute("value", serializedState, null); | |
responseWriter.endElement("input"); | |
} | |
private void writeRenderKitIdField(FacesContext facesContext, ResponseWriter responseWriter) throws IOException | |
{ | |
String defaultRenderKitId = facesContext.getApplication().getDefaultRenderKitId(); | |
if (defaultRenderKitId != null && !RenderKitFactory.HTML_BASIC_RENDER_KIT.equals(defaultRenderKitId)) | |
{ | |
responseWriter.startElement("input", null); | |
responseWriter.writeAttribute("type", "hidden", null); | |
responseWriter.writeAttribute("name", ResponseStateManager.RENDER_KIT_ID_PARAM, null); | |
responseWriter.writeAttribute("value", defaultRenderKitId, null); | |
responseWriter.endElement("input"); | |
} | |
} | |
private String construct(FacesContext facesContext, Object savedState) throws IOException | |
{ | |
byte[] bytes = null; | |
ByteArrayOutputStream baos = null; | |
ObjectOutputStream oos = null; | |
try | |
{ | |
baos = new ByteArrayOutputStream(); | |
oos = new ObjectOutputStream(baos); | |
oos.writeObject(savedState); | |
bytes = baos.toByteArray(); | |
} | |
finally | |
{ | |
if (oos != null) | |
{ | |
try | |
{ | |
oos.close(); | |
} | |
catch(IOException e) | |
{ | |
} | |
finally | |
{ | |
oos = null; | |
} | |
} | |
if (baos != null) | |
{ | |
try | |
{ | |
baos.close(); | |
} | |
catch(IOException e) | |
{ | |
} | |
finally | |
{ | |
baos = null; | |
} | |
} | |
} | |
return new String(new _Hex().encode(bytes), ZIP_CHARSET); | |
} | |
private Object reconstruct(FacesContext facesContext, String encodedState) throws IOException | |
{ | |
byte[] bytes = encodedState.getBytes(ZIP_CHARSET); | |
ByteArrayInputStream input = null; | |
ObjectInputStream s = null; | |
Object object = null; | |
try | |
{ | |
input = new ByteArrayInputStream(bytes); | |
s = new ObjectInputStream(input); | |
object = s.readObject(); | |
} | |
catch (ClassNotFoundException e) | |
{ | |
throw new IOException(e.getMessage()); | |
} | |
finally | |
{ | |
if (s != null) | |
{ | |
try | |
{ | |
s.close(); | |
} | |
catch(IOException e) | |
{ | |
} | |
finally | |
{ | |
s = null; | |
} | |
} | |
if (input != null) | |
{ | |
try | |
{ | |
input.close(); | |
} | |
catch(IOException e) | |
{ | |
} | |
finally | |
{ | |
input = null; | |
} | |
} | |
} | |
return object; | |
} | |
private Object[] getSavedState(FacesContext facesContext) { | |
Object encodedState = | |
facesContext.getExternalContext(). | |
getRequestParameterMap().get(VIEW_STATE_PARAM); | |
if(encodedState==null || (((String) encodedState).length() == 0)) { | |
return null; | |
} | |
Object[] savedState = null; | |
try | |
{ | |
savedState = (Object[])reconstruct(facesContext, (String)encodedState); | |
} | |
catch(IOException e) | |
{ | |
facesContext.getExternalContext().log("Cannot reconstruct view state", e); | |
} | |
if (savedState == null) | |
{ | |
return null; | |
} | |
String restoredViewId = (String)savedState[VIEWID_PARAM]; | |
if (restoredViewId == null) | |
{ | |
return null; | |
} | |
return savedState; | |
} | |
public String getViewState(FacesContext facesContext, Object state) | |
{ | |
if (state == null) | |
{ | |
return null; | |
} | |
Object treeStruct = null; | |
Object compStates = null; | |
if (state instanceof SerializedView) | |
{ | |
SerializedView view = (SerializedView)state; | |
treeStruct = view.getStructure(); | |
compStates = view.getState(); | |
} | |
else if (state instanceof Object[]) | |
{ | |
Object[] structureAndState = (Object[])state; | |
if (structureAndState.length == 2) | |
{ | |
treeStruct = structureAndState[0]; | |
compStates = structureAndState[1]; | |
} | |
else | |
{ | |
throw new FacesException("The state should be an array of Object[] of lenght 2"); | |
} | |
} | |
else | |
{ | |
throw new FacesException("The state should be an array of Object[] of lenght 2, or a SerializedView instance"); | |
} | |
Object[] savedState = new Object[3]; | |
if (facesContext.getApplication().getStateManager().isSavingStateInClient(facesContext)) | |
{ | |
if (treeStruct != null) | |
{ | |
savedState[TREE_PARAM] = treeStruct; | |
} | |
if (compStates != null) | |
{ | |
savedState[STATE_PARAM] = compStates; | |
} | |
} | |
else | |
{ | |
// write viewSequence | |
if (treeStruct != null) | |
{ | |
if (treeStruct instanceof String) | |
{ | |
savedState[TREE_PARAM] = treeStruct; | |
} | |
} | |
} | |
savedState[VIEWID_PARAM] = facesContext.getViewRoot().getViewId(); | |
try | |
{ | |
return construct(facesContext, savedState); | |
} | |
catch(IOException e) | |
{ | |
throw new RuntimeException(e); | |
} | |
} | |
} |