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  
20  package org.apache.myfaces.tobago.fileupload;
21  
22  import org.slf4j.Logger;
23  import org.slf4j.LoggerFactory;
24  import org.apache.myfaces.tobago.internal.util.JndiUtils;
25  import org.apache.myfaces.tobago.internal.webapp.TobagoMultipartFormdataRequest;
26  
27  import javax.faces.FacesException;
28  import javax.faces.application.FacesMessage;
29  import javax.faces.context.FacesContext;
30  import javax.faces.context.FacesContextFactory;
31  import javax.faces.lifecycle.Lifecycle;
32  import javax.naming.InitialContext;
33  import javax.naming.NamingException;
34  import javax.servlet.http.HttpServletRequest;
35  import java.io.File;
36  
37  /**
38   * This FacesContextFactory handles multipart request. Add the tobago-fileupload.jar to your web application.
39   * Configuration:
40   *
41   * <p><blockquote><pre>
42      &lt;env-entry&gt;
43        &lt;description&gt;Set the size limit for uploaded files. Default value is 1 MB.
44          Format: 10 = 10 bytes
45          10k = 10 KB
46          10m = 10 MB
47          1g = 1 GB
48        &lt;/description&gt;
49        &lt;env-entry-name&gt;uploadMaxFileSize&lt;/env-entry-name&gt;
50        &lt;env-entry-type&gt;java.lang.String&lt;/env-entry-type&gt;
51        &lt;env-entry-value&gt;20m&lt;/env-entry-value&gt;
52      &lt;/env-entry&gt;
53      &lt;env-entry&gt;
54        &lt;description&gt;Set the upload repository path for uploaded files.
55               Default value is java.io.tmpdir.&lt;/description&gt;
56        &lt;env-entry-name&gt;uploadRepositoryPath&lt;/env-entry-name&gt;
57        &lt;env-entry-type&gt;java.lang.String&lt;/env-entry-type&gt;
58        &lt;env-entry-value&gt;/tmp&lt;/env-entry-value&gt;
59      &lt;/env-entry&gt;
60   </pre></blockquote><p>
61  
62   *
63   */
64  public class FileUploadFacesContextFactoryImpl extends FacesContextFactory {
65    private static final Logger LOG = LoggerFactory.getLogger(FileUploadFacesContextFactoryImpl.class);
66    private FacesContextFactory facesContextFactory;
67    private String repositoryPath = System.getProperty("java.io.tmpdir");
68    private long maxSize = TobagoMultipartFormdataRequest.ONE_MB;
69  
70    public FileUploadFacesContextFactoryImpl(final FacesContextFactory facesContextFactory) {
71      // TODO get Configuration from env entries in the web.xml or context-param
72      this.facesContextFactory = facesContextFactory;
73      if (LOG.isDebugEnabled()) {
74        LOG.debug("Wrap FacesContext for file upload");
75      }
76      InitialContext ic = null;
77      try {
78        ic = new InitialContext();
79  
80        try {
81          final String repositoryPath = (String) JndiUtils.getJndiProperty(ic, "uploadRepositoryPath");
82          if (repositoryPath != null) {
83            final File file = new File(repositoryPath);
84            if (!file.exists()) {
85              LOG.error("Given repository Path for "
86                  + getClass().getName() + " " + repositoryPath + " doesn't exists");
87            } else if (!file.isDirectory()) {
88              LOG.error("Given repository Path for "
89                  + getClass().getName() + " " + repositoryPath + " is not a directory");
90            } else {
91              this.repositoryPath = repositoryPath;
92            }
93          }
94        } catch (final NamingException ne) {
95          // ignore
96        }
97  
98        try {
99          final String size = (String) JndiUtils.getJndiProperty(ic, "uploadMaxFileSize");
100         maxSize = TobagoMultipartFormdataRequest.getMaxSize(size);
101       } catch (final NamingException ne) {
102         // ignore
103       }
104     } catch (final NamingException e) {
105       // ignore no naming available
106     } finally {
107       if (ic != null) {
108         try {
109           ic.close();
110         } catch (final NamingException e) {
111           // ignore
112         }
113       }
114     }
115     if (LOG.isInfoEnabled()) {
116       LOG.info("Configure uploadMaxFileSize for "+ getClass().getName() + " to "+ this.maxSize);
117       LOG.info("Configure uploadRepositryPath for "+ getClass().getName() + " to "+ this.repositoryPath);
118     }
119   }
120 
121   public FacesContext getFacesContext(
122       final Object context, Object request, final Object response, final Lifecycle lifecycle)
123       throws FacesException {
124     if (request instanceof HttpServletRequest && !(request instanceof TobagoMultipartFormdataRequest)) {
125       final String contentType = ((HttpServletRequest) request).getContentType();
126       if (contentType != null && contentType.toLowerCase().startsWith("multipart/form-data")) {
127         if (LOG.isDebugEnabled()) {
128           LOG.debug("Wrap HttpServletRequest for file upload");
129         }
130         try {
131           request = new TobagoMultipartFormdataRequest((HttpServletRequest) request, repositoryPath, maxSize);
132         } catch (final FacesException e) {
133           LOG.error("", e);
134           final FacesContext facesContext = facesContextFactory.getFacesContext(context, request, response, lifecycle);
135           // TODO  better Message i18n Message?
136           final FacesMessage facesMessage
137               = new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getCause().getMessage(), null);
138           facesContext.addMessage(null, facesMessage);
139           facesContext.renderResponse();
140           return facesContext;
141         }
142       }
143     }
144     return facesContextFactory.getFacesContext(context, request, response, lifecycle);
145   }
146 }