View Javadoc

1   /*
2    * $Id: IncludeResourceLoaderFactory.java,v 1.2 2010/01/27 14:55:37 oeuillot Exp $
3    */
4   package org.rcfaces.core.internal.resource;
5   
6   import java.io.File;
7   import java.io.FileInputStream;
8   import java.io.FileNotFoundException;
9   import java.io.FileOutputStream;
10  import java.io.IOException;
11  import java.io.InputStream;
12  import java.io.OutputStream;
13  import java.net.HttpRetryException;
14  import java.util.Date;
15  
16  import javax.servlet.RequestDispatcher;
17  import javax.servlet.ServletContext;
18  import javax.servlet.ServletRequest;
19  import javax.servlet.http.HttpServletRequest;
20  import javax.servlet.http.HttpServletResponse;
21  
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  import org.rcfaces.core.internal.lang.ByteBufferInputStream;
25  import org.rcfaces.core.internal.lang.ByteBufferOutputStream;
26  import org.rcfaces.core.internal.util.IncludeHttpServletRequest;
27  import org.rcfaces.core.internal.util.IncludeHttpServletResponse;
28  
29  /**
30   * 
31   * @author Olivier Oeuillot (latest modification by $Author: oeuillot $)
32   * @version $Revision: 1.2 $ $Date: 2010/01/27 14:55:37 $
33   */
34  
35  public class IncludeResourceLoaderFactory extends AbstractResourceLoaderFactory {
36      private static final String REVISION = "$Revision: 1.2 $";
37  
38      private static final Log LOG = LogFactory
39              .getLog(IncludeResourceLoaderFactory.class);
40  
41      public String getName() {
42          return "Load resource by servlet inclusion.";
43      }
44  
45      public IResourceLoader loadResource(ServletContext context,
46              HttpServletRequest request, HttpServletResponse response, String uri) {
47          return new IncludeResourceLoader(context, request, response, uri);
48      }
49  
50      /**
51       * 
52       * @author Olivier Oeuillot (latest modification by $Author: oeuillot $)
53       * @version $Revision: 1.2 $ $Date: 2010/01/27 14:55:37 $
54       */
55      private static class IncludeResourceLoader implements IResourceLoader {
56          private static final String REVISION = "$Revision: 1.2 $";
57  
58          private static final String TEMP_FILE_PREFIX = "include-resource.";
59  
60          private static final String TEMP_FILE_SUFFIX = ".tmp";
61  
62          private static final int BUFFER_DEFAULT_SIZE = 0;
63  
64          private static final String DEFAULT_CHARSET = "UTF-8";
65  
66          private static final long MEMORY_BUFFER_MAX_SIZE = 4096;
67  
68          private final ServletContext servletContext;
69  
70          private final HttpServletRequest servletRequest;
71  
72          private final HttpServletResponse servletResponse;
73  
74          private final String uri;
75  
76          private int contentLength;
77  
78          private long lastModified;
79  
80          private String contentType;
81  
82          private boolean errored;
83  
84          private boolean bufferInitialized;
85  
86          private File bufferFile;
87  
88          private byte bufferArray[];
89  
90          public IncludeResourceLoader(ServletContext servletContext,
91                  HttpServletRequest servletRequest,
92                  HttpServletResponse servletResponse, String uri) {
93              this.servletContext = servletContext;
94              this.servletRequest = servletRequest;
95              this.servletResponse = servletResponse;
96              this.uri = uri;
97          }
98  
99          public int getContentLength() {
100             if (isErrored()) {
101                 return -1;
102             }
103             return contentLength;
104         }
105 
106         public long getLastModified() {
107             if (isErrored()) {
108                 return -1;
109             }
110             return lastModified;
111         }
112 
113         public String getContentType() {
114             if (isErrored()) {
115                 return null;
116             }
117             return contentType;
118         }
119 
120         public boolean isErrored() {
121             if (errored == false && bufferInitialized == false) {
122                 getContent();
123             }
124             return errored;
125         }
126 
127         public InputStream openStream() {
128             if (isErrored()) {
129                 return null;
130             }
131 
132             if (bufferArray != null) {
133                 return new ByteBufferInputStream(bufferArray);
134             }
135 
136             if (bufferFile != null) {
137                 try {
138                     return new FileInputStream(bufferFile);
139 
140                 } catch (FileNotFoundException e) {
141                     LOG.error("Can not open buffer file '" + bufferFile
142                             + "' for resource url '" + uri + "'.", e);
143                 }
144             }
145 
146             return null;
147         }
148 
149         private void getContent() {
150             if (bufferInitialized) {
151                 return;
152             }
153             bufferInitialized = true;
154 
155             File fileTemp;
156             try {
157                 fileTemp = File.createTempFile(TEMP_FILE_PREFIX,
158                         TEMP_FILE_SUFFIX);
159             } catch (IOException ex) {
160                 LOG.error("Failed to call request " + uri + ".", ex);
161                 errored = true;
162                 return;
163             }
164 
165             try {
166                 OutputStream output = null;
167                 if (fileTemp != null) {
168 
169                     if (LOG.isDebugEnabled()) {
170                         LOG.debug("Use temp file='"
171                                 + fileTemp.getAbsolutePath()
172                                 + "' to store response of resource request '"
173                                 + uri + "'.");
174                     }
175 
176                     try {
177                         output = new FileOutputStream(fileTemp);
178 
179                     } catch (FileNotFoundException ex) {
180                         LOG.error(
181                                 "Can not write into file '" + fileTemp + "'.",
182                                 ex);
183                     }
184                 }
185                 if (output == null) {
186                     output = new ByteBufferOutputStream(BUFFER_DEFAULT_SIZE);
187 
188                     if (LOG.isDebugEnabled()) {
189                         LOG.debug("Use memory byte array (size="
190                                 + BUFFER_DEFAULT_SIZE
191                                 + ") to store response of resource request '"
192                                 + uri + "'.");
193                     }
194                 }
195 
196                 ServletRequest request = new IncludeHttpServletRequest(
197                         servletRequest);
198                 IncludeHttpServletResponse response = IncludeHttpServletResponse
199                         .create(servletResponse, output, DEFAULT_CHARSET);
200 
201                 String requestURI;
202                 if (uri.charAt(0) != '/') {
203                     requestURI = "/" + uri;
204 
205                 } else {
206                     requestURI = uri;
207                 }
208 
209                 if (LOG.isDebugEnabled()) {
210                     LOG.debug("Send request to get resource content of '"
211                             + requestURI + "'.");
212                 }
213 
214                 RequestDispatcher requestDispatcher = servletContext
215                         .getRequestDispatcher(requestURI);
216                 if (requestDispatcher == null) {
217                     LOG.error("Can not get request dispatcher for url '"
218                             + requestURI + "'.");
219                     errored = true;
220                     return;
221                 }
222 
223                 try {
224                     requestDispatcher.include(request, response);
225 
226                 } catch (Exception ex) {
227                     LOG.error("Failed to call request " + uri + ".", ex);
228                     errored = true;
229                     return;
230                 }
231 
232                 try {
233                     output.close();
234 
235                 } catch (IOException ex) {
236                     LOG.error("Can not close buffer !", ex);
237                 }
238 
239                 if (response.getStatus() != HttpServletResponse.SC_OK) {
240                     LOG.error("Invalid response status: "
241                             + response.getStatus());
242                     errored = true;
243                     return;
244                 }
245 
246                 this.lastModified = response.getLastModified();
247                 this.contentLength = response.getContentLength();
248                 this.contentType = response.getContentType();
249 
250                 if (LOG.isDebugEnabled()) {
251                     LOG
252                             .debug("Resource '"
253                                     + uri
254                                     + "' contentType='"
255                                     + contentType
256                                     + "' contentLength="
257                                     + contentLength
258                                     + " lastModified="
259                                     + ((lastModified > 0) ? new Date(
260                                             lastModified).toString() : String
261                                             .valueOf(lastModified)));
262                 }
263 
264                 if (fileTemp != null) {
265                     bufferFile = fileTemp;
266                     bufferFile.deleteOnExit();
267 
268                 } else {
269                     bufferArray = ((ByteBufferOutputStream) output)
270                             .toByteArray();
271                 }
272 
273             } finally {
274                 if (errored && fileTemp != null) {
275                     fileTemp.delete();
276                 }
277             }
278         }
279 
280         protected void finalize() throws Throwable {
281             if (bufferFile != null) {
282                 if (LOG.isDebugEnabled()) {
283                     LOG.debug("Finalize resource loader, delete file '"
284                             + bufferFile.getAbsolutePath() + "'.");
285                 }
286                 try {
287                     bufferFile.delete();
288 
289                 } catch (Throwable th) {
290                     LOG.error("Can not delete file '"
291                             + bufferFile.getAbsolutePath() + "'.", th);
292                 }
293                 bufferFile = null;
294             }
295 
296             super.finalize();
297         }
298     }
299 
300 }