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

Reply via email to