You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by mm...@apache.org on 2007/02/25 09:10:55 UTC
svn commit: r511461 [1/3] - in /myfaces:
core/trunk/api/src/main/java/javax/faces/webapp/
core/trunk/impl/src/main/java/org/apache/myfaces/application/
core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/
core/trunk/impl/src/main/java/org/...
Author: mmarinschek
Date: Sun Feb 25 00:10:54 2007
New Revision: 511461
URL: http://svn.apache.org/viewvc?view=rev&rev=511461
Log:
partial state saving improvement
Added:
myfaces/core/trunk/api/src/main/java/javax/faces/webapp/_DummyPageContextOutWriter.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/BufferedStringWriter.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/EncodeAllComponentUtil.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/FastStringWriter.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/PartialTreeStructureManager.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/PssJspStateManagerImpl.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/PssJspViewHandlerImpl.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/TempServletOutputStream.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/TreeStructComponent.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/UIViewRootWrapper.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/ViewHandlerResponseWrapperHelperImpl.java
Modified:
myfaces/core/trunk/api/src/main/java/javax/faces/webapp/UIComponentTag.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/context/portlet/PortletExternalContextImpl.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/context/servlet/ServletExternalContextImpl.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/taglib/core/ViewTag.java
myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlResponseWriterImpl.java
myfaces/tomahawk/trunk/examples/simple/src/main/webapp/WEB-INF/web.xml
Modified: myfaces/core/trunk/api/src/main/java/javax/faces/webapp/UIComponentTag.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/java/javax/faces/webapp/UIComponentTag.java?view=diff&rev=511461&r1=511460&r2=511461
==============================================================================
--- myfaces/core/trunk/api/src/main/java/javax/faces/webapp/UIComponentTag.java (original)
+++ myfaces/core/trunk/api/src/main/java/javax/faces/webapp/UIComponentTag.java Sun Feb 25 00:10:54 2007
@@ -26,6 +26,7 @@
import javax.faces.application.Application;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
+import javax.faces.component.UIOutput;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.context.ExternalContext;
@@ -35,8 +36,11 @@
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
+import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.Tag;
+import javax.servlet.jsp.tagext.BodyContent;
import java.io.IOException;
+import java.io.Reader;
import java.util.*;
/**
@@ -63,6 +67,12 @@
private static final String UNIQUE_ID_COUNTER_ATTR = UIComponentTag.class.getName() + ".UNIQUE_ID_COUNTER";
+ private static final String PARTIAL_STATE_SAVING_METHOD_PARAM_NAME = "javax.faces.PARTIAL_STATE_SAVING_METHOD";
+ private static final String PARTIAL_STATE_SAVING_METHOD_ON = "true";
+ private static final String PARTIAL_STATE_SAVING_METHOD_OFF = "false";
+
+ private static final String BEFORE_VIEW_CONTEXT = "org.apache.myfaces.BEFORE_VIEW_CONTEXT";
+
protected PageContext pageContext = null;
private Tag _parent = null;
@@ -78,8 +88,36 @@
private ResponseWriter _writer = null;
private Set _childrenAdded = null;
private Set _facetsAdded = null;
+ private Boolean _partialStateSaving = null;
private static Log log = LogFactory.getLog(UIComponentTag.class);
+ private static final int READ_LENGTH = 8000;
+
+ private boolean isPartialStateSavingOn(javax.faces.context.FacesContext context)
+ {
+ if(context == null) throw new NullPointerException("context");
+ if (_partialStateSaving != null) return _partialStateSaving.booleanValue();
+ String stateSavingMethod = context.getExternalContext().getInitParameter(PARTIAL_STATE_SAVING_METHOD_PARAM_NAME);
+ if (stateSavingMethod == null)
+ {
+ _partialStateSaving = Boolean.FALSE; //Specs 10.1.3: default server saving
+ context.getExternalContext().log("No partial state saving method defined, assuming default partial state saving methode off.");
+ }
+ else if (stateSavingMethod.equals(PARTIAL_STATE_SAVING_METHOD_ON))
+ {
+ _partialStateSaving = Boolean.TRUE;
+ }
+ else if (stateSavingMethod.equals(PARTIAL_STATE_SAVING_METHOD_OFF))
+ {
+ _partialStateSaving = Boolean.FALSE;
+ }
+ else
+ {
+ _partialStateSaving = Boolean.FALSE; //Specs 10.1.3: default server saving
+ context.getExternalContext().log("Illegal partial state saving method '" + stateSavingMethod + "', default partial state saving will be used (partial state saving off).");
+ }
+ return _partialStateSaving.booleanValue();
+ }
public UIComponentTag()
@@ -297,6 +335,116 @@
}
/**
+ * Flushes the Writer and adds the content of the Writer ( which is only the direct output
+ * of the JSP if the component uses a dummyWriter wich does not render the Component itself) as
+ * UIOutput component after the current component to the myfaces component tree.
+ * @param writerToFlush
+ * @throws JspException
+ * @throws IOException
+ */
+
+ private void flushWriter( JspWriter writerToFlush ) throws JspException,IOException {
+
+ if (getFacesContext() == null)
+ return;
+ BodyContent tempwriter;
+ _componentInstance = findComponent(_facesContext);
+ if (writerToFlush instanceof BodyContent)
+ {
+ int count = 0;
+ char [] readChars = new char[READ_LENGTH];
+ tempwriter = (BodyContent) writerToFlush;
+ Reader read =tempwriter.getReader();
+ count = read.read(readChars,0,READ_LENGTH);
+ String readString = new String(readChars,0,count);
+ if(!readString.trim().equals(""))
+ {
+ //_componentInstance = findComponent(_facesContext);
+ UIComponentTag parentTag = getParentUIComponentTag(pageContext);
+ addOutputComponentAfterComponent(parentTag,createUIOutputComponentFromString(readString),_componentInstance);
+ tempwriter.clearBody();
+ }
+
+ }
+ else
+ {
+ if (_componentInstance.getParent() == null) {
+ writerToFlush.flush();
+ String beforeViewContent = _facesContext.getExternalContext().getResponse().toString();
+ if((beforeViewContent != null)&&(!beforeViewContent.trim().equals("")))
+ { // BEFORE BODY CONTENT
+ _facesContext.getExternalContext().getRequestMap().put(BEFORE_VIEW_CONTEXT,beforeViewContent);
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Adds an Output Component afert a given component.
+ * @param parentTag the parent tag of the component.
+ * @param outputComponent the component which should be added after this component.
+ * @param component the component after witch the outputComponent should be added.
+ */
+ private void addOutputComponentAfterComponent(UIComponentTag parentTag,
+ UIComponent outputComponent,
+ UIComponent component) {
+ int indexOfComponentInParent = 0;
+ UIComponent parent = component.getParent();
+
+ if (null == parent) {
+ return;
+ }
+ List children = parent.getChildren();
+ indexOfComponentInParent = children.indexOf(component);
+ if (children.size() - 1 == indexOfComponentInParent) {
+ children.add(outputComponent);
+ }
+ else {
+ children.add(indexOfComponentInParent + 1, outputComponent);
+ }
+ parentTag.addChildIdToParentTag(parentTag,outputComponent.getId());
+
+ }
+
+
+ /**
+ * Creates a UIOutput component and fill in the content. The attribute
+ * escape will be set to false. The content will be renderd as it is.
+ * @param content the content of the UIOutput component.
+ * @return A UIOutput component with the content an the attribute escape
+ * set to false.
+ */
+ private UIComponent createUIOutputComponentFromString( String content) {
+ UIOutput outputComponent = null;
+
+ outputComponent = createUIOutputComponent(getFacesContext());
+ outputComponent.setValue(content);
+
+ return outputComponent;
+ }
+
+
+ /**
+ * Creates a UIOutput component with the attribute escape = false. The Value
+ * of the Component will be rendert as it is, which is useful if there are html tags
+ * which should be injectet into the component tree.
+ * @param context the Myfaces Context.
+ * @return A UIOutput Component with escape = false. The String of this Component
+ * will be rendert as it is.
+ */
+ private UIOutput createUIOutputComponent(FacesContext context) {
+ if (context == null) return null;
+ UIOutput outputComponent = null;
+ Application application = context.getApplication();
+ outputComponent = (UIOutput) application.createComponent("javax.faces.HtmlOutputText");
+ outputComponent.setTransient(true);
+ outputComponent.getAttributes().put("escape", Boolean.FALSE);
+ outputComponent.setId(context.getViewRoot().createUniqueId());
+ return outputComponent;
+ }
+
+ /**
* Invoked by the standard jsp processing mechanism when the opening
* tag of a JSF component element is found.
* <p>
@@ -312,6 +460,15 @@
{
setupResponseWriter();
FacesContext facesContext = getFacesContext();
+ if ( isPartialStateSavingOn(facesContext) )
+ {
+ JspWriter writer = pageContext.getOut();
+ try {
+ flushWriter(writer);
+ } catch (IOException e) {
+ log.error(e.toString());
+ }
+ }
UIComponent component = findComponent(facesContext);
if (!component.getRendersChildren() && !isSuppressed())
{
@@ -349,6 +506,21 @@
public int doEndTag()
throws JspException
{
+ if (isPartialStateSavingOn(getFacesContext()))
+ {
+ JspWriter writerToFlush = pageContext.getOut();
+ if (_componentInstance == null) {
+ findComponent(getFacesContext());
+ }
+ if ((!(writerToFlush instanceof BodyContent)) && _componentInstance.getParent() == null) {
+ //add the before view content to the UIViewRoot
+ _componentInstance.getChildren().add(0,
+ createUIOutputComponentFromString((String)
+ _facesContext.getExternalContext().getRequestMap().get(BEFORE_VIEW_CONTEXT)));
+ _facesContext.getExternalContext().getRequestMap().remove(BEFORE_VIEW_CONTEXT);
+ }
+ }
+
popTag();
UIComponent component = getComponentInstance();
removeFormerChildren(component);
@@ -937,9 +1109,16 @@
RenderKit renderKit = renderFactory.getRenderKit(facesContext,
facesContext.getViewRoot().getRenderKitId());
- _writer = renderKit.createResponseWriter(new _PageContextOutWriter(pageContext),
- null /*Default: get the allowed content-types from the accept-header*/,
- pageContext.getRequest().getCharacterEncoding());
+ if (isPartialStateSavingOn(facesContext)) {
+ _writer = renderKit.createResponseWriter(new _DummyPageContextOutWriter(pageContext),
+ null /*Default: get the allowed content-types from the accept-header*/,
+ pageContext.getRequest().getCharacterEncoding());
+ } else {
+ _writer = renderKit.createResponseWriter(new _PageContextOutWriter(pageContext),
+ null /*Default: get the allowed content-types from the accept-header*/,
+ pageContext.getRequest().getCharacterEncoding());
+
+ }
facesContext.setResponseWriter(_writer);
}
}
Added: myfaces/core/trunk/api/src/main/java/javax/faces/webapp/_DummyPageContextOutWriter.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/java/javax/faces/webapp/_DummyPageContextOutWriter.java?view=auto&rev=511461
==============================================================================
--- myfaces/core/trunk/api/src/main/java/javax/faces/webapp/_DummyPageContextOutWriter.java (added)
+++ myfaces/core/trunk/api/src/main/java/javax/faces/webapp/_DummyPageContextOutWriter.java Sun Feb 25 00:10:54 2007
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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 javax.faces.webapp;
+
+import javax.servlet.jsp.PageContext;
+import java.io.Writer;
+import java.io.IOException;
+
+/**
+ * This Writer is a dummy Writer.
+ *
+ * @author Martin Haimberger
+ */
+class _DummyPageContextOutWriter
+ extends Writer
+{
+ private PageContext _pageContext;
+
+ public _DummyPageContextOutWriter(PageContext pageContext)
+ {
+ _pageContext = pageContext;
+ }
+
+ public void close() throws IOException
+ {
+
+ }
+
+ public void flush() throws IOException
+ {
+
+ }
+
+ public void write(char cbuf[], int off, int len) throws IOException
+ {
+
+ }
+
+ public void write(int c) throws IOException
+ {
+
+ }
+
+ public void write(char cbuf[]) throws IOException
+ {
+
+ }
+
+ public void write(String str) throws IOException
+ {
+
+ }
+
+ public void write(String str, int off, int len) throws IOException
+ {
+
+ }
+
+}
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java?view=diff&rev=511461&r1=511460&r2=511461
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java Sun Feb 25 00:10:54 2007
@@ -52,8 +52,39 @@
extends NavigationHandler
{
private static final Log log = LogFactory.getLog(NavigationHandlerImpl.class);
+ private static final String PARTIAL_STATE_SAVING_METHOD_PARAM_NAME = "javax.faces.PARTIAL_STATE_SAVING_METHOD";
+ private static final String PARTIAL_STATE_SAVING_METHOD_ON = "true";
+ private static final String PARTIAL_STATE_SAVING_METHOD_OFF = "false";
private static final String ASTERISK = "*";
+ private Boolean _partialStateSaving = null;
+
+ private boolean isPartialStateSavingOn(javax.faces.context.FacesContext context)
+ {
+ if(context == null) throw new NullPointerException("context");
+ if (_partialStateSaving != null) return _partialStateSaving.booleanValue();
+ String stateSavingMethod = context.getExternalContext().getInitParameter(PARTIAL_STATE_SAVING_METHOD_PARAM_NAME);
+ if (stateSavingMethod == null)
+ {
+ _partialStateSaving = Boolean.FALSE; //Specs 10.1.3: default server saving
+ context.getExternalContext().log("No partial state saving method defined, assuming default partial state saving methode off.");
+ }
+ else if (stateSavingMethod.equals(PARTIAL_STATE_SAVING_METHOD_ON))
+ {
+ _partialStateSaving = Boolean.TRUE;
+ }
+ else if (stateSavingMethod.equals(PARTIAL_STATE_SAVING_METHOD_OFF))
+ {
+ _partialStateSaving = Boolean.FALSE;
+ }
+ else
+ {
+ _partialStateSaving = Boolean.FALSE; //Specs 10.1.3: default server saving
+ context.getExternalContext().log("Illegal partial state saving method '" + stateSavingMethod + "', default partial state saving will be used (partial state saving off).");
+ }
+ return _partialStateSaving.booleanValue();
+ }
+
private Map _navigationCases = null;
private List _wildcardKeys = new ArrayList();
@@ -102,7 +133,12 @@
ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
//create new view
String newViewId = navigationCase.getToViewId();
- UIViewRoot viewRoot = viewHandler.createView(facesContext, newViewId);
+ UIViewRoot viewRoot = null;
+ if (isPartialStateSavingOn(facesContext)) {
+ viewRoot = viewHandler.restoreView(facesContext,newViewId);
+ } else {
+ viewRoot = viewHandler.createView(facesContext, newViewId);
+ }
facesContext.setViewRoot(viewRoot);
facesContext.renderResponse();
}
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/BufferedStringWriter.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/BufferedStringWriter.java?view=auto&rev=511461
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/BufferedStringWriter.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/BufferedStringWriter.java Sun Feb 25 00:10:54 2007
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.myfaces.application.pss;
+
+import org.apache.myfaces.application.jsp.JspViewHandlerImpl;
+import org.apache.myfaces.application.MyfacesStateManager;
+import org.apache.myfaces.shared_impl.renderkit.html.HtmlLinkRendererBase;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+import javax.faces.application.StateManager;
+import java.io.Writer;
+import java.io.IOException;
+
+/**
+ * @author Martin Haimberger
+ */
+public class BufferedStringWriter extends FastStringWriter {
+
+ private static final Log log = LogFactory.getLog(BufferedStringWriter.class);
+
+ public BufferedStringWriter(FacesContext context, int initialCapcity) {
+ super(initialCapcity);
+ }
+
+ /**
+ * flushes the content of this writer to the given writer.
+ * @param writer the content of this writer is written to the given writer
+ * @throws IOException IOException
+ */
+ public void flushToWriter(Writer writer) throws IOException {
+
+
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ StateManager stateManager = facesContext.getApplication().getStateManager();
+ StateManager.SerializedView serializedView
+ = stateManager.saveSerializedView(facesContext);
+ if (serializedView != null)
+ {
+ //until now we have written to a buffer
+ ResponseWriter bufferWriter = facesContext.getResponseWriter();
+ bufferWriter.flush();
+ //now we switch to real output
+ ResponseWriter realWriter = bufferWriter.cloneWithWriter(writer);
+ facesContext.setResponseWriter(realWriter);
+
+ String bodyStr = _buffer.toString();
+ //if ( stateManager.isSavingStateInClient(facesContext) )
+ //{
+ int form_marker = bodyStr.indexOf(JspViewHandlerImpl.FORM_STATE_MARKER);
+ int url_marker = bodyStr.indexOf(HtmlLinkRendererBase.URL_STATE_MARKER);
+ int lastMarkerEnd = 0;
+ while (form_marker != -1 || url_marker != -1)
+ {
+ if (url_marker == -1 || (form_marker != -1 && form_marker < url_marker))
+ {
+ //replace form_marker
+ realWriter.write(bodyStr, lastMarkerEnd, form_marker - lastMarkerEnd);
+ stateManager.writeState(facesContext, serializedView);
+ lastMarkerEnd = form_marker + JspViewHandlerImpl.FORM_STATE_MARKER_LEN;
+ form_marker = bodyStr.indexOf(JspViewHandlerImpl.FORM_STATE_MARKER, lastMarkerEnd);
+ }
+ else
+ {
+ //replace url_marker
+ realWriter.write(bodyStr, lastMarkerEnd, url_marker - lastMarkerEnd);
+ if (stateManager instanceof MyfacesStateManager)
+ {
+ ((MyfacesStateManager)stateManager).writeStateAsUrlParams(facesContext,
+ serializedView);
+ }
+ else
+ {
+ log.error("Current StateManager is no MyfacesStateManager and does not support saving state in url parameters.");
+ }
+ lastMarkerEnd = url_marker + HtmlLinkRendererBase.URL_STATE_MARKER_LEN;
+ url_marker = bodyStr.indexOf(HtmlLinkRendererBase.URL_STATE_MARKER, lastMarkerEnd);
+ }
+ }
+ realWriter.write(bodyStr, lastMarkerEnd, bodyStr.length() - lastMarkerEnd);
+ /*}
+ else
+ {
+ realWriter.write( bodyStr );
+ } */
+ }
+ else
+ {
+ // Save state in Server Session ... only write out the content
+ ResponseWriter bufferWriter = facesContext.getResponseWriter();
+ bufferWriter.flush();
+ //now we switch to real output
+ ResponseWriter realWriter = bufferWriter.cloneWithWriter(writer);
+ facesContext.setResponseWriter(realWriter);
+
+ String bodyStr = _buffer.toString();
+
+ realWriter.write( bodyStr );
+ }
+ }
+
+ public int length() {
+ return _buffer.length();
+ }
+
+
+ }
\ No newline at end of file
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/EncodeAllComponentUtil.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/EncodeAllComponentUtil.java?view=auto&rev=511461
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/EncodeAllComponentUtil.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/EncodeAllComponentUtil.java Sun Feb 25 00:10:54 2007
@@ -0,0 +1,45 @@
+package org.apache.myfaces.application.pss;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+import java.util.Iterator;
+
+/**
+ * @author Martin Haimberger
+ */
+public class EncodeAllComponentUtil {
+ /**
+ * ensure that this util class can not be instanciated
+ */
+ private EncodeAllComponentUtil(){}
+
+ /**
+ * Encodes a whole UI-Component Tree or a part of the tree.
+ * @param context The facescontext
+ * @param component The base of the tree or the part or the tree
+ * @throws IOException thrown Exception
+ */
+
+ public static void encodeAll(FacesContext context, UIComponent component)
+ throws IOException
+ {
+ if (!component.isRendered()) {
+ return;
+ }
+
+ component.encodeBegin(context);
+ if (component.getRendersChildren()) {
+ component.encodeChildren(context);
+ }
+ else if (component.getChildCount() > 0) {
+ Iterator kids = component.getChildren().iterator();
+ while (kids.hasNext()) {
+ UIComponent kid = (UIComponent) kids.next();
+ encodeAll(context,kid);
+ }
+ }
+
+ component.encodeEnd(context);
+ }
+}
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/FastStringWriter.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/FastStringWriter.java?view=auto&rev=511461
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/FastStringWriter.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/FastStringWriter.java Sun Feb 25 00:10:54 2007
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.myfaces.application.pss;
+
+/**
+ * @author Martin Haimberger
+ */
+import java.io.IOException;
+import java.io.Writer;
+
+public class FastStringWriter extends Writer {
+
+ protected StringBuffer _buffer;
+
+ // ------------------------------------------------------------ Constructors
+
+ /**
+ * <p>Constructs a new <code>FastStringWriter</code> instance
+ * using the default capacity of <code>16</code>.</p>
+ */
+ public FastStringWriter() {
+ _buffer = new StringBuffer();
+ }
+
+ /**
+ * <p>Constructs a new <code>FastStringWriter</code> instance
+ * using the specified <code>initialCapacity</code>.</p>
+ *
+ * @param initialCapacity specifies the initial capacity of the buffer
+ *
+ * @throws IllegalArgumentException if initialCapacity is less than zero
+ */
+ public FastStringWriter(int initialCapacity) {
+ if (initialCapacity < 0) {
+ throw new IllegalArgumentException();
+ }
+ _buffer = new StringBuffer(initialCapacity);
+ }
+
+ // ----------------------------------------------------- Methods from Writer
+
+ public void write(char cbuf[], int off, int len) throws IOException {
+ if ((off < 0) || (off > cbuf.length) || (len < 0) ||
+ ((off + len) > cbuf.length) || ((off + len) < 0)) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return;
+ }
+ _buffer.append(cbuf, off, len);
+ }
+
+ /**
+ * noop
+ * @throws IOException
+ */
+ public void flush() throws IOException {
+ }
+
+ /**
+ * noop
+ * @throws IOException
+ */
+ public void close() throws IOException {
+ }
+
+ // ---------------------------------------------------------- Public Methods
+
+ public void write(String str) {
+ write(str, 0, str.length());
+ }
+
+ public void write(String str, int off, int len) {
+ _buffer.append(str.substring(off, off + len));
+ }
+
+ public StringBuffer getBuffer() {
+ return _buffer;
+ }
+
+ public String toString() {
+ return _buffer.toString();
+ }
+
+}
\ No newline at end of file
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/PartialTreeStructureManager.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/PartialTreeStructureManager.java?view=auto&rev=511461
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/PartialTreeStructureManager.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/pss/PartialTreeStructureManager.java Sun Feb 25 00:10:54 2007
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.myfaces.application.pss;
+
+import org.apache.myfaces.shared_impl.util.ClassUtils;
+
+import javax.faces.component.UIViewRoot;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.util.*;
+
+/**
+ * @author Martin Haimberger
+ */
+public class PartialTreeStructureManager
+{
+ public static final String PARTIAL_STATE_CLASS_IDS = PartialTreeStructureManager.class.getName() + ".PARTIAL_STATE_MANAGER_COMPONENT_IDS";
+
+ private FacesContext _facesContext;
+
+ public PartialTreeStructureManager(FacesContext facesContext)
+ {
+ _facesContext = facesContext;
+ }
+
+ public Object buildTreeStructureToSave(UIViewRoot viewRoot, FacesContext facesContext)
+ {
+ Object savedStateTree = viewRoot.processSaveState(facesContext);
+ if (viewRoot instanceof UIViewRootWrapper) {
+ // the first call ... all components have to be saved in the template
+ return internalBuildInitalTreeStructureToSave(viewRoot,facesContext, savedStateTree,0);
+ }
+ else return internalBuildTreeStructureToSave(viewRoot,facesContext, savedStateTree,0);
+ }
+
+ private TreeStructComponent internalBuildInitalTreeStructureToSave(UIComponent component,FacesContext facesContext, Object state, int childIndex)
+ {
+
+ Object myState = null;
+ Map facetStateMap = null;
+ List childrenStateList = null;
+
+
+ if (state != null)
+ {
+ myState = ((Object[])state)[0];
+ facetStateMap = (Map)((Object[])state)[1];
+ childrenStateList = (List)((Object[])state)[2];
+ }
+ else
+ {
+
+ }
+ TreeStructComponent structComp = new TreeStructComponent(convertStringToComponentClassId(facesContext,component.getClass().getName()),
+ component.getId(),myState,component.isTransient());
+
+ //children
+ if (component.getChildCount() > 0)
+ {
+ List childList = component.getChildren();
+ List structChildList = new ArrayList();
+ for (int i = 0, len = childList.size(); i < len; i++)
+ {
+ UIComponent child = (UIComponent)childList.get(i);
+ if (!child.isTransient())
+ {
+
+ TreeStructComponent structChild = internalBuildInitalTreeStructureToSave(child,facesContext,childrenStateList != null ? childrenStateList.get(childIndex++):null,0);
+ structChildList.add(structChild);
+ }
+ else
+ {
+
+ child.setTransient(false);
+ TreeStructComponent structChild = internalBuildInitalTreeStructureToSave(child,facesContext,child.processSaveState(facesContext),0);
+ structChildList.add(structChild);
+ child.setTransient(true);
+
+ }
+ }
+ TreeStructComponent[] childArray = (TreeStructComponent[])structChildList.toArray(new TreeStructComponent[structChildList.size()]);
+ structComp.setChildren(childArray);
+ }
+
+ //facets
+ Map facetMap = component.getFacets();
+ if (!facetMap.isEmpty())
+ {
+ List structFacetList = new ArrayList();
+ for (Iterator it = facetMap.entrySet().iterator(); it.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry)it.next();
+ UIComponent child = (UIComponent)entry.getValue();
+ String facetName = (String)entry.getKey();
+ if (!child.isTransient())
+ {
+
+ TreeStructComponent structChild = internalBuildInitalTreeStructureToSave(child,facesContext,facetStateMap.get(facetName),0);
+ structFacetList.add(new Object[] {facetName, structChild});
+ }
+ else
+ {
+ // this is a transient Component ... save it anyway
+ child.setTransient(false);
+ TreeStructComponent structChild = internalBuildInitalTreeStructureToSave(child,facesContext,child.processSaveState(facesContext),0);
+ structFacetList.add(new Object[] {facetName, structChild});
+ child.setTransient(true);
+ }
+ }
+ Object[] facetArray = structFacetList.toArray(new Object[structFacetList.size()]);
+ structComp.setFacets(facetArray);
+ }
+
+ return structComp;
+ }
+
+ private TreeStructComponent internalBuildTreeStructureToSave(UIComponent component,FacesContext facesContext, Object state, int childIndex)
+ {
+
+ Object myState = null;
+ Map facetStateMap = null;
+ List childrenStateList = null;
+
+
+ if (state != null)
+ {
+ myState = ((Object[])state)[0];
+ facetStateMap = (Map)((Object[])state)[1];
+ childrenStateList = (List)((Object[])state)[2];
+ }
+ else
+ {
+
+ }
+ TreeStructComponent structComp = new TreeStructComponent(convertStringToComponentClassId(facesContext,component.getClass().getName()),
+ component.getId(),myState,component.isTransient());
+
+ //children
+ if (component.getChildCount() > 0)
+ {
+ List childList = component.getChildren();
+ List structChildList = new ArrayList();
+ for (int i = 0, len = childList.size(); i < len; i++)
+ {
+ UIComponent child = (UIComponent)childList.get(i);
+ if (!child.isTransient())
+ {
+
+ TreeStructComponent structChild = internalBuildTreeStructureToSave(child,facesContext,childrenStateList != null ? childrenStateList.get(childIndex++):null,0);
+ structChildList.add(structChild);
+ }
+ }
+ TreeStructComponent[] childArray = (TreeStructComponent[])structChildList.toArray(new TreeStructComponent[structChildList.size()]);
+ structComp.setChildren(childArray);
+ }
+
+ //facets
+ Map facetMap = component.getFacets();
+ if (!facetMap.isEmpty())
+ {
+ List structFacetList = new ArrayList();
+ for (Iterator it = facetMap.entrySet().iterator(); it.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry)it.next();
+ UIComponent child = (UIComponent)entry.getValue();
+ String facetName = (String)entry.getKey();
+ if (!child.isTransient())
+ {
+
+ TreeStructComponent structChild = internalBuildTreeStructureToSave(child,facesContext,facetStateMap.get(facetName),0);
+ structFacetList.add(new Object[] {facetName, structChild});
+ }
+
+ }
+ Object[] facetArray = structFacetList.toArray(new Object[structFacetList.size()]);
+ structComp.setFacets(facetArray);
+ }
+
+ return structComp;
+ }
+
+
+
+ public UIViewRoot restoreTreeStructure(FacesContext facesContext,Object treeStructRoot)
+ {
+ if (treeStructRoot instanceof TreeStructComponent)
+ {
+ return (UIViewRoot)internalRestoreTreeStructure((TreeStructComponent)treeStructRoot,facesContext);
+ }
+ else
+ {
+ throw new IllegalArgumentException("TreeStructure of type " + treeStructRoot.getClass().getName() + " is not supported.");
+ }
+ }
+
+ private UIComponent internalRestoreTreeStructure(TreeStructComponent treeStructComp,FacesContext facesContext)
+ {
+ String compClass = convertComponentClassIdToString(facesContext,treeStructComp.getComponentClass());
+ String compId = treeStructComp.getComponentId();
+ UIComponent component = (UIComponent) ClassUtils.newInstance(compClass);
+ component.setId(compId);
+ component.setTransient(treeStructComp.isTransient());
+
+ //children
+ TreeStructComponent[] childArray = treeStructComp.getChildren();
+ if (childArray != null)
+ {
+ List childList = component.getChildren();
+ for (int i = 0, len = childArray.length; i < len; i++)
+ {
+ UIComponent child = internalRestoreTreeStructure(childArray[i],facesContext);
+ childList.add(child);
+ }
+ }
+
+ //facets
+ Object[] facetArray = treeStructComp.getFacets();
+ if (facetArray != null)
+ {
+ Map facetMap = component.getFacets();
+ for (int i = 0, len = facetArray.length; i < len; i++)
+ {
+ TreeStructComponent structChild = (TreeStructComponent)((Object[])facetArray[i])[1];
+ String facetName = (String)((Object[])facetArray[i])[0];
+ UIComponent child = internalRestoreTreeStructure(structChild,facesContext);
+ facetMap.put(facetName, child);
+ }
+ }
+
+
+ return component;
+ }
+
+
+
+ private String convertComponentClassIdToString(FacesContext facesContext,Integer classId){
+ Object[] idmaps = (Object[])facesContext.getExternalContext().getApplicationMap().get(PARTIAL_STATE_CLASS_IDS);
+
+ if ( idmaps== null)
+ {
+ // create on
+ idmaps = new Object[2];
+ // contains the Classid as Map
+ idmaps[0] = new HashMap();
+ idmaps[1] = new HashMap();
+ facesContext.getExternalContext().getApplicationMap().put(PARTIAL_STATE_CLASS_IDS,idmaps);
+ }
+ return (String)((HashMap)idmaps[0]).get(classId);
+ }
+
+ private Integer convertStringToComponentClassId(FacesContext facesContext,String stringToConvert){
+
+ // if it was the first time and the wrapper was use ... use the original UIViewRoot
+
+ if (stringToConvert.equalsIgnoreCase("org.apache.myfaces.application.pss.UIViewRootWrapper")) {
+ stringToConvert = "javax.faces.component.UIViewRoot";
+ }
+
+ Object[] idmaps = (Object[])facesContext.getExternalContext().getApplicationMap().get(PARTIAL_STATE_CLASS_IDS);
+
+ if ( idmaps== null)
+ {
+ // create on
+ idmaps = new Object[2];
+ // contains the Classid as Map
+ idmaps[0] = new HashMap();
+ idmaps[1] = new HashMap();
+ }
+ Integer idInMap = (Integer)((HashMap)idmaps[1]).get(stringToConvert);
+ HashMap idToStringMap=((HashMap)idmaps[0]);
+ HashMap stringToIdMap=((HashMap)idmaps[1]);
+
+ if (idInMap == null )
+ {
+ // this type is not jet registerd ... register now
+ Integer id = new Integer(stringToIdMap.size());
+
+ stringToIdMap.put(stringToConvert,id);
+ idToStringMap.put(id,stringToConvert);
+ }
+ facesContext.getExternalContext().getApplicationMap().put(PARTIAL_STATE_CLASS_IDS,idmaps);
+ return (Integer)stringToIdMap.get(stringToConvert);
+ }
+
+
+}