View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.custom.fileupload;
20  
21  import org.apache.myfaces.component.UserRoleUtils;
22  import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
23  import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
24  import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRenderer;
25  import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
26  import org.apache.myfaces.webapp.filter.MultipartRequestWrapper;
27  
28  import org.apache.commons.fileupload.FileItem;
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  
32  import javax.faces.component.UIComponent;
33  import javax.faces.context.FacesContext;
34  import javax.faces.FacesException;
35  import javax.faces.context.ResponseWriter;
36  import javax.faces.context.ExternalContext;
37  import javax.faces.convert.ConverterException;
38  import javax.servlet.ServletRequest;
39  import javax.servlet.http.HttpServletRequestWrapper;
40  import java.io.IOException;
41  import java.util.Map;
42  
43  /**
44   * Renderer for the HtmlInputFileUpload component.
45   * <p>
46   * See also class AbstractHtmlInputFileUpload.
47   * 
48   * @JSFRenderer
49   *   renderKitId = "HTML_BASIC" 
50   *   family = "javax.faces.Input"
51   *   type = "org.apache.myfaces.FileUpload"
52   * 
53   * @author Manfred Geiler (latest modification by $Author: lu4242 $)
54   * @version $Revision: 782515 $ $Date: 2009-06-07 22:28:42 -0500 (Sun, 07 Jun 2009) $
55   */
56  public class HtmlFileUploadRenderer
57          extends HtmlRenderer
58  {
59      private static final Log log = LogFactory.getLog(HtmlFileUploadRenderer.class);
60  
61      public void encodeEnd(FacesContext facesContext, UIComponent uiComponent)
62              throws IOException
63      {
64          super.encodeEnd(facesContext, uiComponent); //check for NP
65  
66          ResponseWriter writer = facesContext.getResponseWriter();
67          writer.startElement(HTML.INPUT_ELEM, uiComponent);
68          writer.writeAttribute(HTML.TYPE_ATTR, HTML.FILE_ATTR, null);
69          String clientId = uiComponent.getClientId(facesContext);
70          renderId(facesContext, uiComponent);
71          writer.writeAttribute(HTML.NAME_ATTR, clientId, null);
72          UploadedFile value = (UploadedFile)((HtmlInputFileUpload)uiComponent).getValue();
73          if (value != null)
74          {
75              if( value.getName() != null )
76              {
77                  writer.writeAttribute(HTML.VALUE_ATTR, value.getName(), null);
78              }
79          }
80          HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent, HTML.INPUT_FILE_PASSTHROUGH_ATTRIBUTES_WITHOUT_DISABLED);
81          if (isDisabled(facesContext, uiComponent))
82          {
83              writer.writeAttribute(HTML.DISABLED_ATTR, Boolean.TRUE, null);
84          }
85  
86          writer.endElement(HTML.INPUT_ELEM);
87      }
88  
89      protected boolean isDisabled(FacesContext facesContext, UIComponent uiComponent)
90      {
91          if (!UserRoleUtils.isEnabledOnUserRole(uiComponent))
92          {
93              //if the user is not enabled, the component is
94              //disabled, so it should return true.
95              return true;
96          }
97          else
98          {
99              if (uiComponent instanceof HtmlInputFileUpload)
100             {
101                 return ((HtmlInputFileUpload)uiComponent).isDisabled();
102             }
103             else
104             {
105                 return RendererUtils.getBooleanAttribute(uiComponent, HTML.DISABLED_ATTR, false);
106             }
107         }
108     }
109 
110     private void setSubmittedValueForImplementation(
111         FacesContext facesContext, UIComponent uiComponent, FileItem fileItem)
112     {
113         try
114         {
115             UploadedFile upFile;
116             String implementation =
117                 ((HtmlInputFileUpload)uiComponent).getStorage();
118             if (implementation == null || implementation.length() == 0)
119             {
120                 implementation = "default";
121             }
122             if (("memory").equals(implementation))
123             {
124                 upFile = new UploadedFileDefaultMemoryImpl(fileItem);
125             }
126             else if (("default").equals(implementation))
127             {
128                 if (fileItem.isInMemory())
129                 {
130                     upFile = new UploadedFileDefaultMemoryImpl(fileItem);
131                 }
132                 else
133                 {
134                     upFile = new UploadedFileDefaultFileImpl(fileItem);                    
135                 }
136             }
137             else //"file" case
138             {
139                 upFile = new UploadedFileDefaultFileImpl(fileItem);
140             }
141 
142             ((HtmlInputFileUpload)uiComponent).setSubmittedValue(upFile);
143             ((HtmlInputFileUpload)uiComponent).setValid(true);
144         }
145         catch (IOException ioe)
146         {
147             throw new FacesException(
148                 "Exception while processing file upload for file-input : "
149                     + uiComponent.getClientId(facesContext), ioe);
150         }
151     }
152 
153     /**
154      * Handle the postback of a form containing a fileUpload component.
155      * <p>
156      * The browser request will have been in "multi-part-mime" format, where
157      * the normal http post is in one part, and the file being uploaded is
158      * in another. Hopefully JSF has been configured so that this special
159      * request is wrapped in a custom ServletRequest that allows us to
160      * fetch that extra data....
161      */
162     public void decode(FacesContext facesContext, UIComponent uiComponent)
163     {
164         super.decode(facesContext, uiComponent); //check for NP
165 
166         //MultipartWrapper might have been wrapped again by one or more additional
167         //Filters. We try to find the MultipartWrapper, but if a filter has wrapped
168         //the ServletRequest with a class other than HttpServletRequestWrapper
169         //this will fail.
170         Object request = facesContext.getExternalContext().getRequest();
171         if (!(request instanceof ServletRequest)) {
172             ExternalContext externalContext = facesContext.getExternalContext();
173             Map fileItems = (Map)externalContext.getRequestMap().
174                     get(MultipartRequestWrapper.UPLOADED_FILES_ATTRIBUTE);
175             FileItem fileItem = null;
176             if (fileItems != null) {
177                 String paramName = uiComponent.getClientId(facesContext);
178                 fileItem = (FileItem) fileItems.get(paramName);
179             }
180             if (fileItem != null)
181             {
182                 setSubmittedValueForImplementation(facesContext, uiComponent, fileItem);
183             }
184             return;
185         }
186         if(facesContext.getExternalContext().getRequest() instanceof ServletRequest)
187         {
188             ServletRequest multipartRequest = (ServletRequest)facesContext.getExternalContext().getRequest();
189             while (multipartRequest != null &&
190                     !(multipartRequest instanceof MultipartRequestWrapper))
191             {
192                 if (multipartRequest instanceof HttpServletRequestWrapper)
193                 {
194                     multipartRequest = ((HttpServletRequestWrapper)multipartRequest).getRequest();
195                 }
196                 else
197                 {
198                     multipartRequest = null;
199                 }
200             }
201 
202             if (multipartRequest != null)
203             {
204                 MultipartRequestWrapper mpReq = (MultipartRequestWrapper)multipartRequest;
205 
206                 String paramName = uiComponent.getClientId(facesContext);
207                 FileItem fileItem = mpReq.getFileItem(paramName);
208                 if (fileItem != null)
209                 {
210                     setSubmittedValueForImplementation(facesContext, uiComponent, fileItem);
211                 }
212             }
213         }
214     }
215 
216     public Object getConvertedValue(FacesContext context, UIComponent component, Object submittedValue) throws ConverterException
217     {
218         if(submittedValue instanceof UploadedFile)
219         {
220             UploadedFile file = (UploadedFile) submittedValue;
221 
222             if(file.getSize()>0 && file.getName()!=null && file.getName().length()>0)
223             {
224                 return file;
225             }
226         }
227 
228         return null;
229     }
230 }