Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
$URL: https://source.sakaiproject.org/svn/jsf/tags/sakai-10.0/jsf-widgets/src/java/org/sakaiproject/jsf/renderer/InputFileUploadRenderer.java $ $Id: InputFileUploadRenderer.java 105077 2012-02-24 22:54:29Z ottenhoff@longsight.com $ Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008 The Sakai Foundation Licensed under the Educational Community 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.opensource.org/licenses/ECL-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.sakaiproject.jsf.renderer;
 
 import java.io.File;
 
 
 
 public class InputFileUploadRenderer extends Renderer
 {
     private static final String ID_INPUT_ELEMENT = ".uploadId";
 
     private static final String ID_HIDDEN_ELEMENT = ".hiddenId";
 
     private static final String ATTR_REQUEST_DECODED = ".decoded";
 
     private static final String[] PASSTHROUGH_ATTRIBUTES = { "accept""accesskey",
             "align""disabled""maxlength""readonly""size""style""tabindex" };
 
     public static final String ATTR_UPLOADS_DONE = "sakai.uploads.done";
 
     public void encodeBegin(FacesContext contextUIComponent component)
             throws IOException
     {
         if (!component.isRendered()) return;
 
         ResponseWriter writer = context.getResponseWriter();
         String clientId = component.getClientId(context);
         //HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
 
         // check that the structure of the form is valid
         boolean atDecodeTime = false;
         String errorMessage = checkForErrors(contextcomponentclientIdatDecodeTime);
         if (errorMessage != null)
         {
             addFacesMessage(contextclientIderrorMessage);
         }
 
         // output field that allows user to upload a file
         writer.startElement("input"null);
         writer.writeAttribute("type""file"null);
         writer.writeAttribute("name"clientId + null);
         String styleClass = (String) RendererUtil.getAttribute(contextcomponent"styleClass");
         if (styleClass != nullwriter.writeAttribute("class"styleClassnull);
         boolean writeNullPassthroughAttributes = false;
                 writeNullPassthroughAttributescontextcomponent);
         writer.endElement("input");
 
         // another comment
         // output hidden field that helps test that the filter is working right
         writer.startElement("input"null);
         writer.writeAttribute("type""hidden"null);
         writer.writeAttribute("name"clientId + null);
         writer.writeAttribute("value""filter_is_functioning_properly"null);
         writer.endElement("input");
     }
 
     public void decode(FacesContext contextUIComponent comp)
     {
         UIInput component = (UIInputcomp;
         if (!component.isRendered()) return;
 
         ExternalContext external = context.getExternalContext();
        HttpServletRequest request = (HttpServletRequestexternal.getRequest();
        String clientId = component.getClientId(context);
        String directory = (String) RendererUtil.getAttribute(contextcomponent"directory");
        // mark that this component has had decode() called during request
        // processing
        request.setAttribute(clientId + "true");
        // check for user errors and developer errors
        boolean atDecodeTime = true;
        String errorMessage = checkForErrors(contextcomponentclientIdatDecodeTime);
        if (errorMessage != null)
        {
            addFacesMessage(contextclientIderrorMessage);
            return;
        }
        // get the file item
        FileItem item = getFileItem(contextcomponent);
        if (item.getName() == null || item.getName().length() == 0)
        {
            if (component.isRequired())
            {
                addFacesMessage(contextclientId"Please specify a file.");
                component.setValid(false);
            }
            return;
        }
        if (directory == null || directory.length() == 0)
        {
            // just passing on the FileItem as the value of the component, without persisting it.
            component.setSubmittedValue(item);
        }
        else
        {
            // persisting to a permenent file in a directory.
            // pass on the server-side filename as the value of the component.
            File dir = new File(directory);
            String filename = item.getName();
            filename = filename.replace('\\','/'); // replaces Windows path seperator character "\" with "/"
            filename = filename.substring(filename.lastIndexOf("/")+1);
            File persistentFile = new File(dirfilename);
            try
            {
                item.write(persistentFile);
                component.setSubmittedValue(persistentFile.getPath());
            }
            catch (Exception ex)
            {
                throw new FacesException(ex);
            }
         }
    }


    
Check for errors (both developer errors and user errors) - return a user-friendly error message describing the error, or null if there are no errors.
    private static String checkForErrors(FacesContext contextUIComponent component,
            String clientIdboolean atDecodeTime)
    {
        ExternalContext external = context.getExternalContext();
        HttpServletRequest request = (HttpServletRequestexternal.getRequest();
        UIForm form = null;
        try
        {
        	form = getForm(component);
        }
        catch (IllegalArgumentException e)
        {
        	// there are more than one nested form - thats not OK!
        	return "DEVELOPER ERROR: The <inputFileUpload> tag must be enclosed in just ONE form.  Nested forms confuse the browser.";
        }
        if (form == null || !"multipart/form-data".equals(RendererUtil.getAttribute(contextform"enctype")))
        {
            return "DEVELOPER ERROR: The <inputFileUpload> tag must be enclosed in a <h:form enctype=\"multipart/form-data\"> tag.";
        }
        // check tag attributes
        String directory = (String) RendererUtil.getAttribute(contextcomponent"directory");
        if (directory != null && directory.length() != 0)
        {
            // the tag is configured to persist the uploaded files to a directory.
            // check that the specified directory exists, and is writeable
            File dir = new File(directory);
            if (!dir.isDirectory() || !dir.exists())
            {
                return "DEVELOPER ERROR: The directory specified on the <inputFileUpload> tag does not exist or is not writable.\n"
                + "Check the permissions on directory:\n"
                + dir;
            }
        }
        FileItem item = getFileItem(contextcomponent);
        boolean isMultipartRequest = request.getContentType() != null && request.getContentType().startsWith("multipart/form-data");
        boolean wasMultipartRequestFullyParsed = request.getParameter(clientId + ) != null;
        String requestFilterStatus = (Stringrequest.getAttribute("upload.status");
        Object requestFilterUploadLimit = request.getAttribute("upload.limit");
        Exception requestFilterException = (Exceptionrequest.getAttribute("upload.exception");
        boolean wasDecodeAlreadyCalledOnTheRequest = "true".equals(request.getAttribute(clientId + ));
        if (wasDecodeAlreadyCalledOnTheRequest && !atDecodeTime)
        {
            // decode() was already called on the request, and we're now at encode() time - so don't do further error checking
            // as the FileItem may no longer be valid.
            return null;
        }
        // at this point, if its not a multipart request, it doesn't have a file and there isn't an error.
        if (!isMultipartRequestreturn null;
        // check for user errors
        if ("exception".equals(requestFilterStatus))
        {
            return "An error occured while processing the uploaded file.  The error was:\n"
                    + requestFilterException;
        }
        else if ("size_limit_exceeded".equals(requestFilterStatus))
        {
            // the user tried to upload too large a file
            return "The upload size limit of " + requestFilterUploadLimit + "MB has been exceeded.";
        }
        else if (item == null || item.getName() == null || item.getName().length() == 0)
        {
             // The file item will be null if the component was previously not rendered.
             return null;
         }
        else if (item.getSize() == 0)
        {
            return "The filename '"+item.getName()+"' is invalid.  Please select a valid file.";
        }
        if (!wasMultipartRequestFullyParsed)
        {
            return "An error occured while processing the uploaded file.  The error was:\n"
            + "DEVELOPER ERROR: The <inputFileUpload> tag requires a <filter> in web.xml to parse the uploaded file.\n"
            + "Check that the Sakai RequestFilter is properly configured in web.xml.";
        }
        if (item.getName().indexOf("..") >= 0)
        {
            return "The filename '"+item.getName()+"' is invalid.  Please select a valid file.";
        }
        // everything checks out fine! The upload was parsed, and a FileItem
        // exists with a filename and non-zero length
        return null;
    }

    
Return the FileItem (if present) for the given component. Subclasses of this Renderer could get the FileItem in a different way. First, try getting it from the request attributes (Sakai style). Then try getting it from a method called getFileItem() on the HttpServletRequest (unwrapping the request if necessary).
    private static FileItem getFileItem(FacesContext contextUIComponent component)
    {
        String clientId = component.getClientId(context);
        HttpServletRequest request = (HttpServletRequestcontext.getExternalContext().getRequest();
        FileItem item = null;
        String fieldName = clientId + ;
        // first try just getting it from the request attributes,
        // where the Sakai RequestFilter puts it.
        item = (FileItemrequest.getAttribute(fieldName);
        if (item != nullreturn item;
        // For custom filter compatibility (MyFaces for example),
        // walk up the HttpServletRequestWrapper chain looking for a getFileItem() method.
        while (request != null)
        {
	        // call the getFileItem() method by reflection, so as to not introduce a dependency
	        // on MyFaces, and so the wrapper class that has getFileItem() doesn't have to
	        // implement an interface (as long as it has the right method signature it'll work).
	        try
	        {
	            Class reqClass = request.getClass();
	            Method getFileItemMethod = reqClass.getMethod("getFileItem"new Class[] {String.class});
	            Object returned = getFileItemMethod.invoke(requestnew Object[] {fieldName});
	            if (returned instanceof FileItemreturn (FileItemreturned;
	        }
	        catch (NoSuchMethodException nsme)
	        {
	        }
	        catch (InvocationTargetException ite)
	        {
	        }
	        catch (IllegalArgumentException iae)
	        {
	        }
	        catch (IllegalAccessException iaxe)
	        {
	        }
	        // trace up the request wrapper classes, looking for a getFileItem() method
	        if (request instanceof HttpServletRequestWrapper)
	        {
	            request = (HttpServletRequest) ((HttpServletRequestWrapperrequest).getRequest();
	        }
	        else
	        {
	            request = null;
	        }
        }
        return null;
    }
    private static void addFacesMessage(FacesContext contextString clientId,
            String message)
    {
        context.addMessage(clientIdnew FacesMessage(.,
                messagemessage));
    }

    
get containing UIForm from component hierarchy.

Throws:
java.lang.IllegalArgumentException If there is more than one enclosing form - only one form is allowed!
    private static UIForm getForm(UIComponent component)
    {
    	UIForm ret = null;
        while (component != null)
        {
            if (component instanceof UIForm)
            {
            	if (ret != null)
            	{
            		// Cannot have a doubly-nested form!
            		throw new IllegalArgumentException();
            	}
            	ret = (UIFormcomponent;
            }
            component = component.getParent();
        }
        return ret;
    }
New to GrepCode? Check out our FAQ X