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