You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by mc...@apache.org on 2009/06/03 18:05:49 UTC
svn commit: r781452 - in /myfaces/core/branches/2_0_0:
api/src/main/java/javax/faces/view/
impl/src/main/java/org/apache/myfaces/view/
impl/src/main/java/org/apache/myfaces/view/jsp/
Author: mconcini
Date: Wed Jun 3 16:05:49 2009
New Revision: 781452
URL: http://svn.apache.org/viewvc?rev=781452&view=rev
Log:
MYFACES-2231 - JSPViewDeclarationLanguage initial impl check-in.
Modified:
myfaces/core/branches/2_0_0/api/src/main/java/javax/faces/view/ViewDeclarationLanguage.java
myfaces/core/branches/2_0_0/impl/src/main/java/org/apache/myfaces/view/ViewDeclarationLanguageBase.java
myfaces/core/branches/2_0_0/impl/src/main/java/org/apache/myfaces/view/jsp/JspViewDeclarationLanguage.java
Modified: myfaces/core/branches/2_0_0/api/src/main/java/javax/faces/view/ViewDeclarationLanguage.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2_0_0/api/src/main/java/javax/faces/view/ViewDeclarationLanguage.java?rev=781452&r1=781451&r2=781452&view=diff
==============================================================================
--- myfaces/core/branches/2_0_0/api/src/main/java/javax/faces/view/ViewDeclarationLanguage.java (original)
+++ myfaces/core/branches/2_0_0/api/src/main/java/javax/faces/view/ViewDeclarationLanguage.java Wed Jun 3 16:05:49 2009
@@ -53,12 +53,12 @@
public void retargetAttachedObjects(FacesContext context, UIComponent topLevelComponent, List<AttachedObjectHandler> handlers)
{
- //TODO: implement impl
+ throw new UnsupportedOperationException();
}
public void retargetMethodExpressions(FacesContext context, UIComponent topLevelComponent)
{
- //TODO: implement impl
+ throw new UnsupportedOperationException();
}
}
Modified: myfaces/core/branches/2_0_0/impl/src/main/java/org/apache/myfaces/view/ViewDeclarationLanguageBase.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2_0_0/impl/src/main/java/org/apache/myfaces/view/ViewDeclarationLanguageBase.java?rev=781452&r1=781451&r2=781452&view=diff
==============================================================================
--- myfaces/core/branches/2_0_0/impl/src/main/java/org/apache/myfaces/view/ViewDeclarationLanguageBase.java (original)
+++ myfaces/core/branches/2_0_0/impl/src/main/java/org/apache/myfaces/view/ViewDeclarationLanguageBase.java Wed Jun 3 16:05:49 2009
@@ -62,7 +62,6 @@
public abstract class ViewDeclarationLanguageBase extends ViewDeclarationLanguage
{
- private static final Log log = LogFactory.getLog(ViewDeclarationLanguageBase.class);
/**
* Process the specification required algorithm that is generic to all PDL.
*
@@ -71,15 +70,8 @@
*/
public UIViewRoot createView(FacesContext context, String viewId)
{
- if (context == null)
- {
- throw new NullPointerException("context");
- }
-
- if (viewId == null)
- {
- throw new NullPointerException("viewId");
- }
+ checkNull(context, "context");
+ checkNull(viewId, "viewId");
try
{
@@ -125,181 +117,8 @@
protected abstract String calculateViewId(FacesContext context, String viewId);
protected abstract void sendSourceNotFound(FacesContext context, String message);
-
- @Override
- public void retargetMethodExpressions(FacesContext context, UIComponent topLevelComponent)
- {
- checkNull(context, "context");
- checkNull(topLevelComponent, "topLevelComponent");
- BeanInfo beanInfo = (BeanInfo)topLevelComponent.getAttributes().get(UIComponent.BEANINFO_KEY);
- if(beanInfo == null)
- {
- return; // should we log an error here? spec doesn't say one way or the other so leaving it alone for now.
- }
-
- PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
- for(PropertyDescriptor curDescriptor : descriptors)
- {
- ExpressionFactory expressionFactory = null;
- ValueExpression valueExpression = null;
- MethodExpression attributeMethodExpression = null;
- Class expectedReturn = null;
- Class expectedParams[] = null;
-
- if(curDescriptor.getValue("type") != null || curDescriptor.getValue("method-signature") == null)
- {
- continue;
- }
-
- String targets = null;
- valueExpression = (ValueExpression)curDescriptor.getValue("targets");
- if(valueExpression != null)
- {
- targets = (String)valueExpression.getValue(context.getELContext());
- }
-
- if(targets == null)
- {
- targets = curDescriptor.getName();
- }
-
- if(targets == null)
- {
- continue; //not explicitly part of the algorithm, but could lead to an NPE if we don't check this
- }
-
- String[] targetArray = targets.split(" ");
- for (String curTarget : targetArray)
- {
- UIComponent target = topLevelComponent.findComponent(curTarget);
- if(target == null)
- {
- log.error("target not found");
- continue;
- }
-
- String name = curDescriptor.getName();
-
- ValueExpression attributeValueExpression = (ValueExpression)topLevelComponent.getAttributes().get(name);
-
- if(attributeValueExpression == null)
- {
- log.error("attributeValueExpression not found");
- continue;
- }
-
- if(expressionFactory == null)
- { //initialize expression factory if hasn't been used yet
- expressionFactory = context.getApplication().getExpressionFactory();
- }
-
- boolean isAction = name.equals("action"),
- isActionListener = name.equals("actionListener"),
- isValidator = name.equals("validator"),
- isValueChangeListener = name.equals("valueChangeListener");
-
- String expressionString = attributeValueExpression.getExpressionString();
-
- if(isAction)
- expectedReturn = Object.class;
- else
- expectedReturn = Void.class;
-
- if(isAction)
- {
- expectedParams = new Class[]{};
- attributeMethodExpression = expressionFactory.createMethodExpression(context.getELContext(), expressionString, expectedReturn, expectedParams);
- ((ActionSource2) target).setActionExpression(attributeMethodExpression);
- }
- else if(isActionListener)
- {
- expectedParams = new Class[]{ActionEvent.class};
- attributeMethodExpression = expressionFactory.createMethodExpression(context.getELContext(), expressionString, expectedReturn, expectedParams);
- ((ActionSource2) target).addActionListener(new MethodExpressionActionListener(attributeMethodExpression));
- }
- else if(isValidator)
- {
- expectedParams = new Class[]{FacesContext.class,UIComponent.class,Object.class};
- attributeMethodExpression = expressionFactory.createMethodExpression(context.getELContext(), expressionString, expectedReturn, expectedParams);
- ((EditableValueHolder) target).addValidator(new MethodExpressionValidator(attributeMethodExpression));
- }
- else if(isValueChangeListener)
- {
- expectedParams = new Class[]{ValueChangeEvent.class};
- attributeMethodExpression = expressionFactory.createMethodExpression(context.getELContext(), expressionString, expectedReturn, expectedParams);
- ((EditableValueHolder) target).addValueChangeListener(new MethodExpressionValueChangeListener(attributeMethodExpression));
- }
- else
- {
- //TODO: implement here - derive attribute name from method-signature
- //If name is not equal to any of the previously listed strings, call getExpressionString() on the attributeValueExpression and use that string to create a MethodExpression
- //where the signature is created based on the value of the "method-signature" attribute of the <composite:attribute /> tag.
-
- //Otherwise, assume that the MethodExpression should be placed in the components attribute set. The runtme must create the MethodExpression instance based on the value of the "method-signature" attribute.
- }
-
-
- }
- }
- }
-
- @Override
- public void retargetAttachedObjects(FacesContext context,
- UIComponent topLevelComponent, List<AttachedObjectHandler> handlers)
- {
- checkNull(context, "context");
- checkNull(topLevelComponent, "topLevelComponent");
- checkNull(handlers, "handlers");
-
- BeanInfo beanInfo = (BeanInfo)topLevelComponent.getAttributes().get(UIComponent.BEANINFO_KEY);
-
- if(beanInfo == null)
- {
- log.error("BeanInfo not found");
- return;
- }
-
- BeanDescriptor beanDescriptor = beanInfo.getBeanDescriptor();
- List<AttachedObjectTarget> targetList = (List<AttachedObjectTarget>)beanDescriptor.getValue(AttachedObjectTarget.ATTACHED_OBJECT_TARGETS_KEY);
-
- for (AttachedObjectHandler curHandler : handlers)
- {
- String forAttributeValue = curHandler.getFor();
-
- for(AttachedObjectTarget curTarget : targetList)
- {
- List<UIComponent> targetUIComponents = curTarget.getTargets(topLevelComponent);
- String curTargetName = curTarget.getName();
-
- if( (curHandler instanceof ActionSource2AttachedObjectHandler) && curHandler instanceof ActionSource2AttachedObjectTarget)
- {
- applyAttachedObjects(context,targetUIComponents, curHandler);
- break;
- }
- if( (curHandler instanceof EditableValueHolderAttachedObjectHandler) && curHandler instanceof EditableValueHolderAttachedObjectTarget)
- {
- applyAttachedObjects(context,targetUIComponents, curHandler);
- break;
- }
- if( (curHandler instanceof ValueHolderAttachedObjectHandler) && curHandler instanceof ValueHolderAttachedObjectTarget)
- {
- applyAttachedObjects(context,targetUIComponents, curHandler);
- break;
- }
- }
- }
- }
-
- private void applyAttachedObjects(FacesContext context, List<UIComponent> targetUIComponents, AttachedObjectHandler curHandler)
- {
- for (UIComponent target : targetUIComponents)
- {
- curHandler.applyAttachedObject(context, target);
- }
- }
-
- private void checkNull(final Object o, final String param)
+ protected void checkNull(final Object o, final String param)
{
if (o == null)
{
Modified: myfaces/core/branches/2_0_0/impl/src/main/java/org/apache/myfaces/view/jsp/JspViewDeclarationLanguage.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2_0_0/impl/src/main/java/org/apache/myfaces/view/jsp/JspViewDeclarationLanguage.java?rev=781452&r1=781451&r2=781452&view=diff
==============================================================================
--- myfaces/core/branches/2_0_0/impl/src/main/java/org/apache/myfaces/view/jsp/JspViewDeclarationLanguage.java (original)
+++ myfaces/core/branches/2_0_0/impl/src/main/java/org/apache/myfaces/view/jsp/JspViewDeclarationLanguage.java Wed Jun 3 16:05:49 2009
@@ -20,16 +20,39 @@
import java.beans.BeanInfo;
import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Locale;
import javax.faces.FacesException;
+import javax.faces.FactoryFinder;
+import javax.faces.application.Application;
import javax.faces.application.Resource;
+import javax.faces.application.StateManager;
+import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewRoot;
+import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+import javax.faces.render.RenderKit;
+import javax.faces.render.RenderKitFactory;
import javax.faces.view.StateManagementStrategy;
import javax.faces.view.ViewMetadata;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import javax.servlet.jsp.jstl.core.Config;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.application.DefaultViewHandlerSupport;
import org.apache.myfaces.application.ViewHandlerSupport;
+import org.apache.myfaces.application.jsp.JspViewHandlerImpl;
+import org.apache.myfaces.application.jsp.ViewResponseWrapper;
+import org.apache.myfaces.shared_impl.config.MyfacesConfig;
+import org.apache.myfaces.shared_impl.renderkit.html.util.JavascriptUtils;
import org.apache.myfaces.view.ViewDeclarationLanguageBase;
/**
@@ -40,6 +63,12 @@
*/
public class JspViewDeclarationLanguage extends ViewDeclarationLanguageBase
{
+ private static final Log log = LogFactory.getLog(JspViewDeclarationLanguage.class);
+ public static final String FORM_STATE_MARKER = "<!-...@-->";
+ public static final int FORM_STATE_MARKER_LEN = FORM_STATE_MARKER.length();
+
+ private static final String AFTER_VIEW_TAG_CONTENT_PARAM = JspViewDeclarationLanguage.class + ".AFTER_VIEW_TAG_CONTENT";
+
private ViewHandlerSupport _cachedViewHandlerSupport;
/**
@@ -47,8 +76,9 @@
*/
public JspViewDeclarationLanguage()
{
- // TODO: IMPLEMENT HERE
- }
+ if (log.isTraceEnabled())
+ log.trace("New JspViewDeclarationLanguage instance created");
+ }
/**
* {@inheritDoc}
@@ -56,7 +86,30 @@
@Override
public void buildView(FacesContext context, UIViewRoot view) throws IOException
{
- // TODO: IMPLEMENT HERE
+ ExternalContext externalContext = context.getExternalContext();
+ ServletResponse response = (ServletResponse)externalContext.getResponse();
+ String viewId = view.getViewId();
+ ViewResponseWrapper wrappedResponse = new ViewResponseWrapper((HttpServletResponse) response);
+
+ externalContext.setResponse(wrappedResponse);
+ try
+ {
+ externalContext.dispatch(viewId);
+ }
+ finally
+ {
+ externalContext.setResponse(response);
+ }
+
+ boolean errorResponse = wrappedResponse.getStatus() < 200 || wrappedResponse.getStatus() > 299;
+ if (errorResponse)
+ {
+ wrappedResponse.flushToWrappedResponse();
+ return;
+ }
+
+ // store the wrapped response in the request, so it is thread-safe
+ externalContext.getRequestMap().put(AFTER_VIEW_TAG_CONTENT_PARAM, wrappedResponse);
}
/**
@@ -65,8 +118,7 @@
@Override
public BeanInfo getComponentMetadata(FacesContext context, Resource componentResource)
{
- // TODO: IMPLEMENT HERE
- return null;
+ throw new UnsupportedOperationException();
}
/**
@@ -75,8 +127,7 @@
@Override
public Resource getScriptComponentResource(FacesContext context, Resource componentResource)
{
- // TODO: IMPLEMENT HERE
- return null;
+ throw new UnsupportedOperationException();
}
/**
@@ -88,15 +139,8 @@
// Not necessary given that this method always returns null, but staying true to
// the spec.
- if (context == null)
- {
- throw new NullPointerException ("context must not be null");
- }
-
- if (viewId == null)
- {
- throw new NullPointerException ("viewId must not be null");
- }
+ checkNull(context, "context");
+ checkNull(viewId, "viewId");
// JSP impl must return null.
@@ -109,8 +153,102 @@
@Override
public void renderView(FacesContext context, UIViewRoot view) throws IOException
{
- // TODO: IMPLEMENT HERE
- }
+ checkNull(context, "context");
+ checkNull(view, "view");
+
+ // do not render the view if the rendered attribute for the view is false
+ if (!view.isRendered())
+ {
+ if (log.isTraceEnabled())
+ log.trace("View is not rendered");
+ return;
+ }
+
+ ExternalContext externalContext = context.getExternalContext();
+
+ String viewId = context.getViewRoot().getViewId();
+
+ if (log.isTraceEnabled())
+ log.trace("Rendering JSP view: " + viewId);
+
+ ServletResponse response = (ServletResponse) externalContext.getResponse();
+ ServletRequest request = (ServletRequest) externalContext.getRequest();
+
+ Locale locale = view.getLocale();
+ response.setLocale(locale);
+ Config.set(request, Config.FMT_LOCALE, context.getViewRoot().getLocale());
+
+ buildView(context, view);
+
+ // handle character encoding as of section 2.5.2.2 of JSF 1.1
+ if (externalContext.getRequest() instanceof HttpServletRequest)
+ {
+ HttpServletRequest httpServletRequest = (HttpServletRequest) externalContext.getRequest();
+ HttpSession session = httpServletRequest.getSession(false);
+
+ if (session != null)
+ {
+ session.setAttribute(ViewHandler.CHARACTER_ENCODING_KEY, response.getCharacterEncoding());
+ }
+ }
+
+ // render the view in this method (since JSF 1.2)
+ RenderKitFactory renderFactory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
+ RenderKit renderKit = renderFactory.getRenderKit(context, view.getRenderKitId());
+
+ ResponseWriter responseWriter = context.getResponseWriter();
+ if (responseWriter == null)
+ {
+ responseWriter = renderKit.createResponseWriter(response.getWriter(), null,
+ ((HttpServletRequest) externalContext.getRequest()).getCharacterEncoding());
+ context.setResponseWriter(responseWriter);
+ }
+
+ ResponseWriter oldResponseWriter = responseWriter;
+ StateMarkerAwareWriter stateAwareWriter = null;
+
+ StateManager stateManager = context.getApplication().getStateManager();
+ if (stateManager.isSavingStateInClient(context))
+ {
+ stateAwareWriter = new StateMarkerAwareWriter();
+
+ // Create a new response-writer using as an underlying writer the stateAwareWriter
+ // Effectively, all output will be buffered in the stateAwareWriter so that later
+ // this writer can replace the state-markers with the actual state.
+ responseWriter = oldResponseWriter.cloneWithWriter(stateAwareWriter);
+ context.setResponseWriter(responseWriter);
+ }
+
+ actuallyRenderView(context, view);
+
+ context.setResponseWriter(oldResponseWriter);
+
+ //We're done with the document - now we can write all content
+ //to the response, properly replacing the state-markers on the way out
+ //by using the stateAwareWriter
+ if (stateManager.isSavingStateInClient(context))
+ {
+ stateAwareWriter.flushToWriter(response.getWriter());
+ }
+ else
+ {
+ stateManager.saveView(context);
+ }
+
+ // Final step - we output any content in the wrappedResponse response from above to the response,
+ // removing the wrappedResponse response from the request, we don't need it anymore
+ ViewResponseWrapper afterViewTagResponse = (ViewResponseWrapper) externalContext.getRequestMap().get(
+ AFTER_VIEW_TAG_CONTENT_PARAM);
+ externalContext.getRequestMap().remove(AFTER_VIEW_TAG_CONTENT_PARAM);
+
+ if (afterViewTagResponse != null)
+ {
+ afterViewTagResponse.flushToWriter(response.getWriter(),
+ context.getExternalContext().getResponseCharacterEncoding());
+ }
+
+ response.flushBuffer();
+ }
/**
* {@inheritDoc}
@@ -118,8 +256,12 @@
@Override
public UIViewRoot restoreView(FacesContext context, String viewId)
{
- // TODO: IMPLEMENT HERE
- return null;
+ Application application = context.getApplication();
+ ViewHandler applicationViewHandler = application.getViewHandler();
+ String renderKitId = applicationViewHandler.calculateRenderKitId(context);
+ String calculatedViewId = calculateViewId(context, viewId);
+ UIViewRoot viewRoot = application.getStateManager().restoreView(context, calculatedViewId, renderKitId);
+ return viewRoot;
}
@Override
@@ -127,7 +269,7 @@
{
if (_cachedViewHandlerSupport == null)
{
- _cachedViewHandlerSupport = null; // TODO: IMPLEMENT HERE
+ _cachedViewHandlerSupport = new DefaultViewHandlerSupport();
}
return _cachedViewHandlerSupport.calculateViewId(context, viewId);
@@ -153,7 +295,138 @@
public StateManagementStrategy getStateManagementStrategy(
FacesContext context, String viewId)
{
- // TODO implement here
return null;
}
+
+ /**
+ * Render the view now - properly setting and resetting the response writer
+ */
+ private void actuallyRenderView(FacesContext facesContext,
+ UIViewRoot viewToRender) throws IOException {
+ // Set the new ResponseWriter into the FacesContext, saving the old one aside.
+ ResponseWriter responseWriter = facesContext.getResponseWriter();
+
+ //Now we actually render the document
+ // Call startDocument() on the ResponseWriter.
+ responseWriter.startDocument();
+
+ // Call encodeAll() on the UIViewRoot
+ viewToRender.encodeAll(facesContext);
+
+ // Call endDocument() on the ResponseWriter
+ responseWriter.endDocument();
+
+ responseWriter.flush();
+ }
+
+ /**
+ * Writes the response and replaces the state marker tags with the state information for the current context
+ */
+ private static class StateMarkerAwareWriter extends Writer
+ {
+ private StringBuilder buf;
+
+ public StateMarkerAwareWriter()
+ {
+ this.buf = new StringBuilder();
+ }
+
+ @Override
+ public void close() throws IOException
+ {
+ }
+
+ @Override
+ public void flush() throws IOException
+ {
+ }
+
+ @Override
+ 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;
+ }
+ buf.append(cbuf, off, len);
+ }
+
+ public StringBuilder getStringBuilder()
+ {
+ return buf;
+ }
+
+ public void flushToWriter(Writer writer) throws IOException
+ {
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ StateManager stateManager = facesContext.getApplication().getStateManager();
+
+ StringWriter stateWriter = new StringWriter();
+ ResponseWriter realWriter = facesContext.getResponseWriter();
+ facesContext.setResponseWriter(realWriter.cloneWithWriter(stateWriter));
+
+ Object serializedView = stateManager.saveView(facesContext);
+
+ stateManager.writeState(facesContext, serializedView);
+ facesContext.setResponseWriter(realWriter);
+
+ StringBuilder contentBuffer = getStringBuilder();
+ String state = stateWriter.getBuffer().toString();
+
+ ExternalContext extContext = facesContext.getExternalContext();
+ if (JavascriptUtils.isJavascriptAllowed(extContext) && MyfacesConfig.getCurrentInstance(extContext).isViewStateJavascript()) {
+ // If javascript viewstate is enabled no state markers were written
+ write(contentBuffer, 0, contentBuffer.length(), writer);
+ writer.write(state);
+ } else {
+ // If javascript viewstate is disabled state markers must be replaced
+ int lastFormMarkerPos = 0;
+ int formMarkerPos = 0;
+ // Find all state markers and write out actual state instead
+ while ((formMarkerPos = contentBuffer.indexOf(FORM_STATE_MARKER, formMarkerPos)) > -1)
+ {
+ // Write content before state marker
+ write(contentBuffer, lastFormMarkerPos, formMarkerPos, writer);
+ // Write state and move position in buffer after marker
+ writer.write(state);
+ formMarkerPos += FORM_STATE_MARKER_LEN;
+ lastFormMarkerPos = formMarkerPos;
+ }
+ // Write content after last state marker
+ if (lastFormMarkerPos < contentBuffer.length()) {
+ write(contentBuffer, lastFormMarkerPos, contentBuffer.length(), writer);
+ }
+ }
+
+ }
+
+ /**
+ * Writes the content of the specified StringBuffer from index
+ * <code>beginIndex</code> to index <code>endIndex - 1</code>.
+ *
+ * @param contentBuffer the <code>StringBuffer</code> to copy content from
+ * @param beginIndex the beginning index, inclusive.
+ * @param endIndex the ending index, exclusive
+ * @param writer the <code>Writer</code> to write to
+ * @throws IOException if an error occurs writing to specified <code>Writer</code>
+ */
+ private void write(StringBuilder contentBuffer, int beginIndex, int endIndex, Writer writer) throws IOException {
+ int index = beginIndex;
+ int bufferSize = 2048;
+ char[] bufToWrite = new char[bufferSize];
+
+ while (index < endIndex)
+ {
+ int maxSize = Math.min(bufferSize, endIndex - index);
+
+ contentBuffer.getChars(index, index + maxSize, bufToWrite, 0);
+ writer.write(bufToWrite, 0, maxSize);
+
+ index += bufferSize;
+ }
+ }
+ }
+
}