1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.resource;
20
21 import java.io.BufferedInputStream;
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.FileNotFoundException;
25 import java.io.FileOutputStream;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.OutputStream;
29 import java.net.MalformedURLException;
30 import java.net.URL;
31 import java.util.Map;
32 import java.util.concurrent.ConcurrentHashMap;
33 import javax.faces.FacesException;
34 import javax.faces.application.Resource;
35 import javax.faces.context.FacesContext;
36 import org.apache.myfaces.application.ResourceHandlerImpl;
37 import org.apache.myfaces.shared.resource.ContractResourceLoader;
38 import org.apache.myfaces.shared.resource.ContractResourceLoaderWrapper;
39 import org.apache.myfaces.shared.resource.ResourceMeta;
40 import org.apache.myfaces.shared.util.WebConfigParamUtils;
41
42
43
44
45
46
47
48
49 public class TempDirFileCacheContractResourceLoader extends ContractResourceLoaderWrapper
50 {
51
52 public final static String TEMP_FILES_LOCK_MAP = "oam.rh.con.TEMP_FILES_LOCK_MAP";
53
54
55
56
57 private static final String TEMP_FOLDER_BASE_DIR = "oam-rh-cache/";
58
59
60
61
62 private static final String TEMP_FILE_SUFFIX = ".tmp";
63
64 private final ContractResourceLoader delegate;
65
66 private volatile File _tempDir;
67
68 private int _resourceBufferSize = -1;
69
70 public TempDirFileCacheContractResourceLoader(ContractResourceLoader delegate)
71 {
72 this.delegate = delegate;
73 initialize();
74 }
75
76 protected void initialize()
77 {
78
79 FacesContext facesContext = FacesContext.getCurrentInstance();
80
81
82 Map<String, Object> applicationMap = facesContext.getExternalContext().getApplicationMap();
83 File tempdir = (File) applicationMap.get("javax.servlet.context.tempdir");
84 File imagesDir = new File(tempdir, TEMP_FOLDER_BASE_DIR);
85 if (!imagesDir.exists())
86 {
87 imagesDir.mkdirs();
88 }
89 else
90 {
91
92 deleteDir(imagesDir);
93 imagesDir.mkdirs();
94 }
95 _tempDir = imagesDir;
96
97
98 Map<String, FileProducer> temporalFilesLockMap = new ConcurrentHashMap<String, FileProducer>();
99 facesContext.getExternalContext().getApplicationMap().put(TEMP_FILES_LOCK_MAP, temporalFilesLockMap);
100 }
101
102 private static boolean deleteDir(File dir)
103 {
104 if (dir.isDirectory())
105 {
106 String[] children = dir.list();
107 for (int i = 0; i < children.length; i++)
108 {
109 boolean success = deleteDir(new File(dir, children[i]));
110 if (!success)
111 {
112 return false;
113 }
114 }
115 }
116 return dir.delete();
117 }
118
119 @Override
120 public URL getResourceURL(ResourceMeta resourceMeta)
121 {
122 FacesContext facesContext = FacesContext.getCurrentInstance();
123
124 if (resourceExists(resourceMeta))
125 {
126 File file = createOrGetTempFile(facesContext, resourceMeta);
127
128 try
129 {
130 return file.toURL();
131 }
132 catch (MalformedURLException e)
133 {
134 throw new FacesException(e);
135 }
136 }
137 else
138 {
139 return null;
140 }
141 }
142
143 public InputStream getResourceInputStream(ResourceMeta resourceMeta, Resource resource)
144 {
145 FacesContext facesContext = FacesContext.getCurrentInstance();
146
147 if (resourceExists(resourceMeta))
148 {
149 File file = createOrGetTempFile(facesContext, resourceMeta);
150
151 try
152 {
153 return new BufferedInputStream(new FileInputStream(file));
154 }
155 catch (FileNotFoundException e)
156 {
157 throw new FacesException(e);
158 }
159 }
160 else
161 {
162 return null;
163 }
164 }
165
166 @Override
167 public InputStream getResourceInputStream(ResourceMeta resourceMeta)
168 {
169 return getResourceInputStream(resourceMeta, null);
170 }
171
172 @Override
173 public boolean resourceExists(ResourceMeta resourceMeta)
174 {
175 return super.resourceExists(resourceMeta);
176 }
177
178 @SuppressWarnings("unchecked")
179 private File createOrGetTempFile(FacesContext facesContext, ResourceMeta resourceMeta)
180 {
181 String identifier = resourceMeta.getResourceIdentifier()+"_"+resourceMeta.getContractName();
182 File file = getTemporalFile(resourceMeta);
183 if (!file.exists())
184 {
185 Map<String, FileProducer> map = (Map<String, FileProducer>)
186 facesContext.getExternalContext().getApplicationMap().get(TEMP_FILES_LOCK_MAP);
187
188 FileProducer creator = map.get(identifier);
189
190 if (creator == null)
191 {
192 synchronized(this)
193 {
194 creator = map.get(identifier);
195
196 if (creator == null)
197 {
198 creator = new FileProducer();
199 map.put(identifier, creator);
200 }
201 }
202 }
203
204 if (!creator.isCreated())
205 {
206 creator.createFile(facesContext, resourceMeta, file, this);
207 }
208 }
209 return file;
210 }
211
212 private File getTemporalFile(ResourceMeta resourceMeta)
213 {
214 return new File(_tempDir,
215 resourceMeta.getResourceIdentifier()+"_"+ resourceMeta.getContractName() + TEMP_FILE_SUFFIX);
216 }
217
218 protected void createTemporalFileVersion(FacesContext facesContext, ResourceMeta resourceMeta, File target)
219 {
220 target.mkdirs();
221 target.delete();
222
223 InputStream inputStream = null;
224 FileOutputStream fileOutputStream;
225 try
226 {
227 inputStream = getWrapped().getResourceInputStream(resourceMeta);
228 fileOutputStream = new FileOutputStream(target);
229 byte[] buffer = new byte[this.getResourceBufferSize()];
230
231 pipeBytes(inputStream, fileOutputStream, buffer);
232 }
233 catch (FileNotFoundException e)
234 {
235 throw new FacesException("Unexpected exception while create file:", e);
236 }
237 catch (IOException e)
238 {
239 throw new FacesException("Unexpected exception while create file:", e);
240 }
241 finally
242 {
243 if (inputStream != null)
244 {
245 try
246 {
247 inputStream.close();
248 }
249 catch (IOException e)
250 {
251
252 }
253 }
254 }
255 }
256
257
258
259
260
261 private static void pipeBytes(InputStream in, OutputStream out, byte[] buffer) throws IOException
262 {
263 int length;
264
265 while ((length = (in.read(buffer))) >= 0)
266 {
267 out.write(buffer, 0, length);
268 }
269 }
270
271 public static class FileProducer
272 {
273
274 public volatile boolean created = false;
275
276 public FileProducer()
277 {
278 super();
279 }
280
281 public boolean isCreated()
282 {
283 return created;
284 }
285
286 public synchronized void createFile(FacesContext facesContext,
287 ResourceMeta resourceMeta, File file, TempDirFileCacheContractResourceLoader loader)
288 {
289 if (!created)
290 {
291 loader.createTemporalFileVersion(facesContext, resourceMeta, file);
292 created = true;
293 }
294 }
295 }
296
297 protected int getResourceBufferSize()
298 {
299 if (_resourceBufferSize == -1)
300 {
301 _resourceBufferSize = WebConfigParamUtils.getIntegerInitParameter(
302 FacesContext.getCurrentInstance().getExternalContext(),
303 ResourceHandlerImpl.INIT_PARAM_RESOURCE_BUFFER_SIZE,
304 ResourceHandlerImpl.INIT_PARAM_RESOURCE_BUFFER_SIZE_DEFAULT);
305 }
306 return _resourceBufferSize;
307 }
308
309 public ContractResourceLoader getWrapped()
310 {
311 return delegate;
312 }
313 }