You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@myfaces.apache.org by Mario Ivankovits <ma...@ops.co.at> on 2008/05/16 15:14:59 UTC
Re: svn commit: r656086 [2/2] - in /myfaces/tomahawk/trunk/core:
./ src/main/java/org/apache/myfaces/component/html/util/ src/main/java/org/apache/myfaces/custom/jslistener/
src/main/java/org/apache/myfaces/renderkit/html/util/ src/main/java/org/apache/myf...
Hi!
Simon and me had to spend 5 hours today to track down a problem which in
the end uncovered a nasty bug in TomahawkFacesContextWrapper. In
.release() the delegation was broken (due to a return in the try block).
Bad stuff :-(
Also I found some questionable stuff:
* Some important todos like the arguments for the MultipartRequestWrapper
* A lot of e.printStackTrace()
Is this work in progress? Or is the module already in
"if-one-finds-a-problem-fix-it-yourself"-mode ;-)
Ciao,
Mario
> http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/TomahawkFacesContextWrapper.java?rev=656086&view=auto
> ==============================================================================
> --- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/TomahawkFacesContextWrapper.java (added)
> +++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/TomahawkFacesContextWrapper.java Tue May 13 19:00:38 2008
> @@ -0,0 +1,292 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements. See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership. The ASF licenses this file
> + * to you 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.webapp.filter;
> +
> +import java.lang.reflect.InvocationTargetException;
> +import java.lang.reflect.Method;
> +import java.util.Iterator;
> +
> +import javax.faces.FacesException;
> +import javax.faces.application.Application;
> +import javax.faces.application.FacesMessage;
> +import javax.faces.component.UIViewRoot;
> +import javax.faces.context.ExternalContext;
> +import javax.faces.context.FacesContext;
> +import javax.faces.context.ResponseStream;
> +import javax.faces.context.ResponseWriter;
> +import javax.faces.render.RenderKit;
> +import javax.portlet.PortletResponse;
> +import javax.servlet.http.HttpServletRequest;
> +import javax.servlet.http.HttpServletResponse;
> +
> +import org.apache.commons.fileupload.FileUpload;
> +import org.apache.myfaces.renderkit.html.util.AddResource;
> +import org.apache.myfaces.renderkit.html.util.AddResourceFactory;
> +import org.apache.myfaces.tomahawk.util.ExternalContextUtils;
> +
> +/**
> + * @author Martin Marinschek
> + */
> +public class TomahawkFacesContextWrapper extends FacesContext {
> +
> + private FacesContext delegate=null;
> + private ExternalContext externalContextDelegate=null;
> + private ExtensionsResponseWrapper extensionsResponseWrapper = null;
> +
> + public TomahawkFacesContextWrapper(FacesContext delegate) {
> +
> + this.delegate = delegate;
> +
> + //if(delegate.getExternalContext().getResponse() instanceof PortletResponse) {
> + if(ExternalContextUtils.getRequestType(delegate.getExternalContext()).isPortlet()) {
> + //todo do something here - with the multipart-wrapper. rest should be fine
> + AddResource addResource= AddResourceFactory.getInstance(this);
> + addResource.responseStarted();
> +
> + if (addResource.requiresBuffer())
> + {
> + throw new IllegalStateException("buffering not supported in the portal environment.");
> + }
> + }
> + else {
> + HttpServletResponse httpResponse = (HttpServletResponse) delegate.getExternalContext().getResponse();
> + HttpServletRequest httpRequest = (HttpServletRequest) delegate.getExternalContext().getRequest();
> +
> + HttpServletRequest extendedRequest = httpRequest;
> + HttpServletResponse extendedResponse = httpResponse;
> +
> + // For multipart/form-data requests
> + if (FileUpload.isMultipartContent(httpRequest)) {
> + extendedRequest = new MultipartRequestWrapper(httpRequest, /*todo _uploadMaxFileSize*/-1,
> + /*todo _uploadThresholdSize*/-1, /*todo _uploadRepositoryPath*/null);
> + }
> +
> + AddResource addResource= AddResourceFactory.getInstance(this);
> + addResource.responseStarted();
> +
> + if (addResource.requiresBuffer())
> + {
> + extensionsResponseWrapper = new ExtensionsResponseWrapper(httpResponse);
> + extendedResponse = extensionsResponseWrapper;
> + }
> +
> + externalContextDelegate = new ExternalContextWrapper(
> + delegate.getExternalContext(), extendedRequest, extendedResponse);
> + }
> + }
> +
> + public javax.el.ELContext getELContext() {
> + ;
> + try
> + {
> + return (javax.el.ELContext) delegate.getClass().getMethod("getELContext", null).invoke(delegate, null);
> + }
> + catch (IllegalArgumentException e)
> + {
> + // TODO Auto-generated catch block
> + e.printStackTrace();
> + }
> + catch (SecurityException e)
> + {
> + // TODO Auto-generated catch block
> + e.printStackTrace();
> + }
> + catch (IllegalAccessException e)
> + {
> + // TODO Auto-generated catch block
> + e.printStackTrace();
> + }
> + catch (InvocationTargetException e)
> + {
> + // TODO Auto-generated catch block
> + e.printStackTrace();
> + }
> + catch (NoSuchMethodException e)
> + {
> + // TODO Auto-generated catch block
> + e.printStackTrace();
> + }
> + return null;
> + }
> +
> + public Application getApplication() {
> + return delegate.getApplication();
> + }
> +
> + public Iterator getClientIdsWithMessages() {
> + return delegate.getClientIdsWithMessages();
> + }
> +
> + public ExternalContext getExternalContext() {
> + return externalContextDelegate==null?delegate.getExternalContext():externalContextDelegate;
> + }
> +
> + public FacesMessage.Severity getMaximumSeverity() {
> + return delegate.getMaximumSeverity();
> + }
> +
> + public Iterator getMessages() {
> + return delegate.getMessages();
> + }
> +
> + public Iterator getMessages(String clientId) {
> + return delegate.getMessages(clientId);
> + }
> +
> + public RenderKit getRenderKit() {
> + return delegate.getRenderKit();
> + }
> +
> + public boolean getRenderResponse() {
> + return delegate.getRenderResponse();
> + }
> +
> + public boolean getResponseComplete() {
> + return delegate.getResponseComplete();
> + }
> +
> + public ResponseStream getResponseStream() {
> + return delegate.getResponseStream();
> + }
> +
> + public void setResponseStream(ResponseStream responseStream) {
> + delegate.setResponseStream(responseStream);
> + }
> +
> + public ResponseWriter getResponseWriter() {
> + return delegate.getResponseWriter();
> + }
> +
> + public void setResponseWriter(ResponseWriter responseWriter) {
> + delegate.setResponseWriter(responseWriter);
> + }
> +
> + public UIViewRoot getViewRoot() {
> + return delegate.getViewRoot();
> + }
> +
> + public void setViewRoot(UIViewRoot root) {
> + delegate.setViewRoot(root);
> + }
> +
> + public void addMessage(String clientId, FacesMessage message) {
> + delegate.addMessage(clientId, message);
> + }
> +
> + public void release() {
> +
> + AddResource addResource=null;
> +
> + try
> + {
> + addResource= AddResourceFactory.getInstance(this);
> + if (addResource.requiresBuffer())
> + {
> + if(extensionsResponseWrapper == null) {
> + throw new NullPointerException("When wrapping the faces-context, add-resource told us that no buffer is required, " +
> + "now it is required, and we have a null-extensionsResponseWrapper. Please fix add-resource to be consistent over a single request.");
> + }
> + extensionsResponseWrapper.finishResponse();
> +
> + // write the javascript stuff for myfaces and headerInfo, if needed
> + HttpServletResponse servletResponse = extensionsResponseWrapper.getDelegate();
> + HttpServletRequest servletRequest = (HttpServletRequest) getExternalContext().getRequest();
> +
> + // only parse HTML responses
> + if (extensionsResponseWrapper.getContentType() != null && isValidContentType(extensionsResponseWrapper.getContentType()))
> + {
> + addResource.parseResponse(servletRequest, extensionsResponseWrapper.toString(),
> + servletResponse);
> +
> + addResource.writeMyFacesJavascriptBeforeBodyEnd(servletRequest,
> + servletResponse);
> +
> + if( ! addResource.hasHeaderBeginInfos() ){
> + // writes the response if no header info is needed
> + addResource.writeResponse(servletRequest, servletResponse);
> + return;
> + }
> +
> + // Some headerInfo has to be added
> + addResource.writeWithFullHeader(servletRequest, servletResponse);
> +
> + // writes the response
> + addResource.writeResponse(servletRequest, servletResponse);
> + }
> + else
> + {
> +
> + byte[] responseArray = extensionsResponseWrapper.getBytes();
> +
> + if(responseArray.length > 0)
> + {
> + // When not filtering due to not valid content-type, deliver the byte-array instead of a charset-converted string.
> + // Otherwise a binary stream gets corrupted.
> + servletResponse.getOutputStream().write(responseArray);
> + }
> + }
> + }
> + }
> + catch(Throwable th) {
> + throw new FacesException(th);
> + }
> + finally
> + {
> + if(addResource!=null)
> + addResource.responseFinished();
> + }
> +
> + delegate.release();
> + }
> +
> + public boolean isValidContentType(String contentType)
> + {
> + return contentType.startsWith("text/html") ||
> + contentType.startsWith("text/xml") ||
> + contentType.startsWith("application/xhtml+xml") ||
> + contentType.startsWith("application/xml");
> + }
> +
> + public void renderResponse() {
> + delegate.renderResponse();
> + }
> +
> + public void responseComplete() {
> + delegate.responseComplete();
> + }
> +
> + /*This method is for do not break MyfacesGenericPortlet*/
> + public void setExternalContext(ExternalContext extContext){
> + try
> + {
> + Method method = delegate.getClass().getMethod("setExternalContext", new Class[]{Class.forName("org.apache.myfaces.context.ReleaseableExternalContext")});
> + method.invoke(delegate, new Object[]{extContext});
> + FacesContext.setCurrentInstance(this);
> + }
> + catch (NoSuchMethodException e)
> + {
> + throw new RuntimeException("JSF 1.2 method not implemented: "+e.getMessage());
> + }
> + catch (Exception e)
> + {
> + throw new RuntimeException("Error calling JSF 1.2 method: "+e.getMessage());
> + }
> + }
> +
> +}
>
Ciao,
Mario