1
2
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
32
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
53
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 }