Seam 의 ViewState 의 내용물

private UIViewRoot restoreTree(Object[] tree) throws FacesException { UIComponent c; FacetNode fn; TreeNode tn; for (int i = 0; i < tree.length; i++) { if (tree[i]instanceof FacetNode) { fn = (FacetNode) tree[i]; c = newInstance(fn); tree[i] = c; if (i != fn.parent) { ((UIComponent) tree[fn.parent]).getFacets() .put(fn.facetName, c); } } else { tn = (TreeNode) tree[i]; c = newInstance(tn); tree[i] = c; if (i != tn.parent) { ((UIComponent) tree[tn.parent]).getChildren().add(c); } } } return (UIViewRoot) tree[0]; } 3번의 경우는 같은 클래스의 아래가 참고가 된다.

    private void restoreState(FacesContext context,
                              UIViewRoot root,
                              String renderKitId) {
        ResponseStateManager rsm =
              RenderKitUtils.getResponseStateManager(context, renderKitId);
        Object state;
        if (ReflectionUtils.lookupMethod(rsm.getClass(),
                                         "getState",
                                         FacesContext.class,
                                         String.class) != null) {
            Object[] stateArray =
                  (Object[]) rsm.getState(context, root.getViewId());
            state = stateArray[1];
        } else {
            state = rsm.getComponentStateToRestore(context);
        }
        root.processRestoreState(context, state);
    }
또한 State 의 복구는 UIComponentBase.java 의 아래 메소드도 참고가 될것이다.
    public void restoreState(FacesContext context, Object state) {
        values = (Object[]) state;
        // we need to get the map that knows how to handle attribute/property
        // transparency before we restore its values.
        if (values[0] != null) {
            attributes = new AttributesMap(this,
                                          (HashMap) TypedCollections.dynamicallyCastMap((Map) values[0],
                                                                                        String.class,
                                                                                        Object.class));
        }
        bindings = restoreBindingsState(context, values[1]);
        clientId = (String) values[2];
        id = (String) values[3];
        rendered = ((Boolean) values[4]).booleanValue();
        renderedSet = ((Boolean) values[5]).booleanValue();
        rendererType = (String) values[6];
        List<FacesListener> restoredListeners;
        if (null != (restoredListeners = TypedCollections.dynamicallyCastList((List)
                     restoreAttachedState(context, values[7]), FacesListener.class))) {
            // if there were some listeners registered prior to this
            // method being invoked, merge them with the list to be
            // restored.
            if (null != listeners) {
		listeners.addAll(restoredListeners);
            }
            else {
                listeners = restoredListeners;
            }
        }
        attributesThatAreSet = (List<String>) values[8];
    }
음… 그런데 이게 세큐리티에 문제가 되는데 자바스크립트가 실행이 된다. (방법은 생략) 따라서 암호화를 해야 하는데 web.xml 에 아래와 같이 설정이 필요하다. [crayon] com.sun.faces.ClientStateSavingPassword java.lang.String 암호(비밀번호) [/crayon] 이렇게 하면 ViewState 의 내용을 암호화하여 통신하게 된다. 음… 하지만 이건 ViewState 를 CLIENT에서 저장할때의 이야기고 SERVER에 저정할 수 있는것 같다. [crayon] javax.faces.STATE_SAVING_METHOD server [/crayon] 위와 같이 설정을 하면 서버에서 ViewState 를 관리하기 때문에 번거로운 문제를 회피할 수 있는것 같다. (server 설정이 Default 이다) http://docs.jboss.org/seam/2.3.0.CR1/reference/html/configuration.html
Some JSF implementations have a broken implementation of server-side state saving that interferes with Seam’s conversation propagation. If you have problems with conversation propagation during form submissions, try switching to client-side state saving. You’ll need this in web.xml:
하지만 위와 같이 server-side 에 저장할 경우 몇몇 JSF 가 동일한 Conversation 으로 돌아오지 않을 수 있다고 한다. 참고는 이번에 테스트는 아래와같은 프로그램을 만들어서 ViewState 의 내용물을 확인해볼 수 있다.
package org.ajax4jsf.application;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.lang.reflect.Array;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import javax.faces.component.UIComponent;
import org.ajax4jsf.application.TreeStructureNode.FacetEntry;
import org.apache.xml.security.utils.Base64;
public class Test {
	static ComponentsLoader componentsLoader = new ComponentsLoaderImpl();
	public static String makeIndent(int indent) {
		StringBuffer buffer = new StringBuffer();
		for (int i=0; i<indent; i++) {
			buffer.append(' ');
		}
		return buffer.toString();
	}
	public static void printNode(TreeStructureNode parentNode, int indent, TreeStructureNode node) {
		String indentString = makeIndent(indent);
		if ( parentNode != null ) {
			System.out.print(indentString);
			System.out.println("[PARENT] "+parentNode.getId() );
		}
		System.out.print(indentString);
		System.out.println("[ID] "+node.getId() );
		System.out.print(indentString);
		UIComponent uiComponent = node.restore(componentsLoader);
		System.out.println("[COMPONENT] "+uiComponent );
		if ( node.getFacets() != null ) {
			for (FacetEntry fe : node.getFacets()) {
				System.out.print(indentString);
				System.out.println("[FacetEntry] " + fe.getName() + " (" + fe.getNode()+")");
			}
		}
		System.out.print(indentString);
		System.out.println("-------------------------------------------");
		if ( node.getChildren() != null) {
			for (TreeStructureNode subNode : node.getChildren()) {
				printNode(node, indent+4, subNode);
			}
		}
	}
	public static void main(String[] args) throws Exception {
		String viewState = "H4sIAAAAAAAAAMVYaWwUVR...생략";
		GZIPInputStream gzipInStream = new GZIPInputStream(new BufferedInputStream(new ByteArrayInputStream(Base64.decode(viewState.getBytes()))));
		ObjectInputStream ois = new ObjectInputStream(gzipInStream);
		// #1 - (If exist) timestamp
		// #2 - TreeStructureNode
		printNode(null, 0, (TreeStructureNode)ois.readObject() );
		// #3 - State?
		printState(ois.readObject());
		ois.close();
	}
	public static void printState(Object obj) {
		if ( obj == null ) return;
		if ( obj instanceof Object[] ) {
			for (Object tmp : (Object[])obj) {
				printState(tmp);
			}
			System.out.println("-------------------------------------------");
		} else {
			System.out.println(obj);
		}
	}
}
]]>

Related Posts

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다