/*
* xulfaces : bring XUL power to Java
*
* Copyright (C) 2005 Olivier SCHMITT
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.xulfaces.renderkit;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import javax.faces.FacesException;
import javax.faces.application.StateManager;
import javax.faces.application.StateManager.SerializedView;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.ResponseStateManager;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
*
* @author kito31
* @version $Id: XULResponseStateManager.java,v 1.3 2005/09/17 17:21:21 kito31
* Exp $
*/
public class XULResponseStateManager extends ResponseStateManager {
static ThreadLocal viewStateData = new ThreadLocal();
public static final String XULFACES_VIEW_STATE = "org.xulfaces.ViewState";
private static final String BAD_STATE_SAVING_METHOD = "Saving state in server is not supported (please change it to server in web.xml)";
private static final String BAD_RENDERKIT_ID = "Bad render kit id : should be " + XULRenderKit.XUL_BASIC_RENDER_KIT;
private static final Log log = LogFactory.getLog(XULResponseStateManager.class);
public void writeState(FacesContext context, SerializedView view) throws IOException {
if (log.isDebugEnabled()) {
log.debug("Try to write view state ("+context.getViewRoot().getViewId()+")");
}
if (view == null) {
throw new NullPointerException("Attempt to write a null state.");
}
StateManager stateManager = context.getApplication().getStateManager();
ResponseWriter writer = context.getResponseWriter();
writer.startElement("xfc:viewState", context.getViewRoot());
writer.writeAttribute("id", javax.faces.render.ResponseStateManager.VIEW_STATE_PARAM, null);
if (stateManager.isSavingStateInClient(context)) {
if (log.isDebugEnabled()) {
log.debug("Save state on client");
}
GZIPOutputStream zos = null;
ObjectOutputStream oos = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
zos = new GZIPOutputStream(bos);
oos = new ObjectOutputStream(zos);
oos.writeObject(view.getStructure());
oos.writeObject(view.getState());
oos.close();
zos.close();
String valueToWrite = (new String(Base64.encodeBase64(bos.toByteArray()),"ISO-8859-1"));
if (log.isTraceEnabled()) {
log.trace("Saving on client side : " + valueToWrite);
}
writer.writeAttribute("value",valueToWrite, null);
} else {
if(log.isDebugEnabled()){
log.debug("Save state on server");
log.debug("VIEW_STATE_PARAM " + view.getStructure());
}
writer.writeAttribute("value", view.getStructure(), null);
}
writer.endElement("xfc:viewState");
String renderKitId = context.getApplication().getDefaultRenderKitId();
if (log.isDebugEnabled()) {
log.debug("RENDER_KIT_ID_PARAM " + renderKitId);
}
if (renderKitId != null && renderKitId.equals(XULRenderKit.XUL_BASIC_RENDER_KIT)) {
writer.startElement("xfc:renderKit", context.getViewRoot());
writer.writeAttribute("id", ResponseStateManager.RENDER_KIT_ID_PARAM, "id");
writer.writeAttribute("value", XULRenderKit.XUL_BASIC_RENDER_KIT, "value");
writer.endElement("xfc:renderKit");
} else {
log.error(BAD_RENDERKIT_ID);
throw new FacesException(BAD_RENDERKIT_ID);
}
}
public Object getTreeStructureToRestore(FacesContext context, String viewId) {
if (log.isDebugEnabled()) {
log.debug("Try to restore tree structure ......");
}
StateManager stateManager = context.getApplication().getStateManager();
Map sessionMap = context.getExternalContext().getSessionMap();
Map requestMap = context.getExternalContext().getRequestParameterMap();
if(log.isDebugEnabled()){
if(requestMap.containsKey(KitConstants.XFBRIDGE_REQUEST)){
log.debug("AJAX request detected (from XULFACES_BRIDGE)");
}
}
String viewString = (String) requestMap.get(javax.faces.render.ResponseStateManager.VIEW_STATE_PARAM);
if (log.isDebugEnabled()) {
log.debug("ViewString is " + viewString);
}
Object structure = null;
if (viewString == null) {
return null;
}
if (stateManager.isSavingStateInClient(context)) {
viewStateData.set(null);
if (log.isDebugEnabled()) {
log.debug("State was on client");
}
Object state = null;
ByteArrayInputStream bis = null;
GZIPInputStream gis = null;
ObjectInputStream ois = null;
byte[] bytes =Base64.decodeBase64(viewString.getBytes());
bis = new ByteArrayInputStream(bytes);
try {
gis = new GZIPInputStream(bis);
ois = new ObjectInputStream(gis);
structure = ois.readObject();
state = ois.readObject();
// store the state object temporarily in ThreadLocal viewStateData scope
// until it is processed by getComponentStateToRestore
// which resets it.
viewStateData.set(state);
bis.close();
gis.close();
} catch (IOException e) {
log.error(e.getMessage(),e);
} catch (ClassNotFoundException e) {
log.error(e.getMessage(),e);
}
} else {
if (log.isDebugEnabled()) {
log.debug("State was on server");
}
structure = viewString;
}
return structure;
}
public Object getComponentStateToRestore(FacesContext context) {
Object state = viewStateData.get();
viewStateData.set(null);
return state;
}
@Override
public boolean isPostback(FacesContext context) {
boolean result = context.getExternalContext().getRequestParameterMap().containsKey(
javax.faces.render.ResponseStateManager.VIEW_STATE_PARAM);
if (log.isDebugEnabled()) {
String message;
if (result) {
message = "Postback detected (Must restore UIViewRoot from session)";
} else {
message = "No postback (must creates a new UIViewRoot )";
}
log.debug(message);
}
return result;
}
}