1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.springframework.extensions.webscripts;
20
21 import java.io.File;
22 import java.io.FileFilter;
23 import java.io.FileInputStream;
24 import java.io.FileReader;
25 import java.io.FileWriter;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.Reader;
29 import java.net.MalformedURLException;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.List;
33 import java.util.regex.Pattern;
34
35 import javax.servlet.ServletContext;
36
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39 import org.springframework.extensions.surf.exception.PlatformRuntimeException;
40 import org.springframework.extensions.webscripts.AbstractStore;
41 import org.springframework.extensions.webscripts.ScriptContent;
42 import org.springframework.extensions.webscripts.ScriptLoader;
43 import org.springframework.extensions.webscripts.WebScript;
44 import org.springframework.web.context.ServletContextAware;
45
46 import freemarker.cache.TemplateLoader;
47
48
49
50
51
52
53
54
55
56 public class LocalFileSystemStore extends AbstractStore implements ServletContextAware
57 {
58 private static Log logger = LogFactory.getLog(LocalFileSystemStore.class);
59
60 private String root;
61 private String path;
62 private File rootDir;
63 private ServletContext servletContext;
64
65
66
67
68 public void setServletContext(ServletContext servletContext)
69 {
70 this.servletContext = servletContext;
71 }
72
73 public ServletContext getServletContext()
74 {
75 return this.servletContext;
76 }
77
78 protected File getRootDir()
79 {
80 if (this.rootDir == null)
81 {
82 this.rootDir = new File(getBasePath());
83 }
84
85 return this.rootDir;
86 }
87
88
89
90
91 public void setRoot(String root)
92 {
93 this.root = root;
94 }
95
96 public String getRoot()
97 {
98 return this.root;
99 }
100
101
102
103
104 public void setPath(String path)
105 {
106 this.path = path;
107 }
108
109 public String getPath()
110 {
111 return this.path;
112 }
113
114
115
116
117
118
119 public void init()
120 {
121 if (this.path == null)
122 {
123 this.path = "";
124 }
125 }
126
127
128
129
130
131
132 public boolean isSecure()
133 {
134 return false;
135 }
136
137
138
139
140
141
142 public boolean exists()
143 {
144 if (getRootDir() == null)
145 {
146 if (logger.isDebugEnabled())
147 logger.debug("Root directory for Store does not exist");
148
149 return false;
150 }
151 return getRootDir().exists();
152 }
153
154
155
156
157
158
159 public boolean hasDocument(String documentPath)
160 {
161 File file = new File(toAbsolutePath(documentPath));
162 return (file != null && file.exists() && file.isFile());
163 }
164
165
166
167
168
169
170 public long lastModified(String documentPath) throws IOException
171 {
172 File file = new File(toAbsolutePath(documentPath));
173 if (file == null)
174 {
175 throw new IOException(
176 "Unable to locate file to check modification time: " + documentPath);
177 }
178
179 return file.lastModified();
180 }
181
182
183
184
185
186
187
188 public void updateDocument(String documentPath, String content)
189 throws IOException
190 {
191 File file = new File(toAbsolutePath(documentPath));
192 if (file == null)
193 {
194 throw new IOException(
195 "Unable to locate file for update: " + documentPath);
196 }
197
198 FileWriter fw = new FileWriter(file);
199 fw.write(content);
200 fw.close();
201 }
202
203
204
205
206
207
208 public boolean removeDocument(String documentPath) throws IOException
209 {
210 File file = new File(toAbsolutePath(documentPath));
211 if (file == null)
212 {
213 throw new IOException(
214 "Update to remove document failed, file not found: " + documentPath);
215 }
216
217 return file.delete();
218 }
219
220
221
222
223
224
225
226 public void createDocument(String documentPath, String content)
227 throws IOException
228 {
229
230 if (hasDocument(documentPath))
231 {
232 throw new IOException(
233 "Unable to create document, already exists: " + documentPath);
234 }
235
236 File file = new File(toAbsolutePath(documentPath));
237
238 FileWriter fw = new FileWriter(file);
239 fw.write(content);
240 fw.close();
241 }
242
243
244
245
246
247
248 public InputStream getDocument(String documentPath) throws IOException
249 {
250 File file = new File(toAbsolutePath(documentPath));
251 if (file == null)
252 {
253 throw new IOException(
254 "Unable to get input stream from document: " + documentPath);
255 }
256
257 return new FileInputStream(file);
258 }
259
260
261
262
263
264
265 public String[] getAllDocumentPaths()
266 {
267 List<String> list = new ArrayList<String>(256);
268
269
270 gatherAbsolutePaths(getRootDir().getAbsolutePath(), list);
271
272
273 String[] array = list.toArray(new String[list.size()]);
274
275
276 String absRootPath = getRootDir().getAbsolutePath() + File.separatorChar;
277 int absRootPathLen = absRootPath.length();
278 for (int i = 0; i < array.length; i++)
279 {
280 array[i] = array[i].substring(absRootPathLen);
281
282
283 array[i] = array[i].replace("\\", "/");
284 }
285
286 return array;
287 }
288
289
290
291
292 public String[] getDocumentPaths(String path, boolean includedSubPaths, String documentPattern)
293 {
294 String regexPattern = documentPattern.replaceAll("\\*", ".*");
295
296 if (!regexPattern.startsWith(".*"))
297 {
298 regexPattern = ".*" + regexPattern;
299 }
300
301 return getDocumentPathsByRegEx(path, regexPattern, includedSubPaths);
302 }
303
304
305
306
307
308
309
310
311
312
313
314
315
316 protected String[] getDocumentPathsByRegEx(String path, String regexPattern, boolean traverseChildren)
317 {
318 PatternFileFilter filter = new PatternFileFilter(regexPattern);
319
320 String absParentPath = toAbsolutePath(path);
321 int absParentPathLen = absParentPath.length() - 1;
322 File f = new File(absParentPath);
323
324 List<File> fileList = listPath(f, filter, traverseChildren);
325
326 String[] paths = new String[fileList.size()];
327 for (int i = 0; i < fileList.size(); i++)
328 {
329 String thePath = ((File) fileList.get(i)).getPath();
330 paths[i] = thePath.substring(absParentPathLen);
331
332
333 paths[i] = paths[i].replace("\\", "/");
334 }
335
336 return paths;
337 }
338
339
340
341
342
343
344 public String[] getDescriptionDocumentPaths()
345 {
346 return getDocumentPathsByRegEx("/", ".*\\.desc\\.xml", true);
347 }
348
349
350
351
352
353
354 public String[] getScriptDocumentPaths(WebScript script)
355 {
356 String scriptPaths = script.getDescription().getId() + ".*";
357 return getDocumentPathsByRegEx("/", scriptPaths, false);
358 }
359
360
361
362
363
364
365 public ScriptLoader getScriptLoader()
366 {
367 return new LocalFileSystemStoreScriptLoader();
368 }
369
370
371
372
373
374
375 public TemplateLoader getTemplateLoader()
376 {
377 return new LocalFileSystemStoreTemplateLoader();
378 }
379
380
381
382
383
384
385 public String getBasePath()
386 {
387 String fullPath = this.path;
388
389 if (this.root != null)
390 {
391 if (!root.endsWith("/"))
392 {
393 root += "/";
394 }
395
396 if (root.startsWith("."))
397 {
398
399 fullPath = getRealPath(this.root.substring(1)) + this.path;
400 }
401 else
402 {
403 fullPath = this.root + this.path;
404 }
405 }
406
407 return fullPath;
408 }
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424 public String getRealPath(String path)
425 {
426 String realPath = servletContext.getRealPath(path);
427 if (realPath != null && realPath.endsWith(java.io.File.separator))
428 {
429 realPath = realPath.substring(0, realPath.length() - 1);
430 }
431
432
433 realPath = realPath.replace("/", java.io.File.separator);
434 realPath = realPath.replace("\\", java.io.File.separator);
435
436 return realPath;
437 }
438
439
440
441
442
443
444
445
446 protected String toAbsolutePath(String documentPath)
447 {
448 return getRootDir().getAbsolutePath() + File.separatorChar + documentPath;
449 }
450
451 protected void gatherAbsolutePaths(String absPath, List<String> list)
452 {
453 File file = new File(absPath);
454 if (file.exists())
455 {
456 if (file.isFile())
457 {
458 list.add(absPath);
459 }
460 else if (file.isDirectory())
461 {
462
463 String[] childDocumentPaths = file.list();
464 for (int i = 0; i < childDocumentPaths.length; i++)
465 {
466 String childAbsPath = absPath + File.separatorChar + childDocumentPaths[i];
467 gatherAbsolutePaths(childAbsPath, list);
468 }
469 }
470 }
471 }
472
473
474
475
476
477
478 protected class LocalFileSystemStoreScriptLoader implements ScriptLoader
479 {
480
481
482
483 public ScriptContent getScript(String path)
484 {
485 ScriptContent sc = null;
486 if (hasDocument(path))
487 {
488 sc = new LocalFileSystemStoreScriptContent(path);
489 }
490 return sc;
491 }
492 }
493
494
495
496
497
498
499 private class LocalFileSystemStoreTemplateLoader implements TemplateLoader
500 {
501
502
503
504 public void closeTemplateSource(Object templateSource)
505 throws IOException
506 {
507
508
509 }
510
511
512
513
514 public Object findTemplateSource(String name) throws IOException
515 {
516 LocalFileSystemStoreTemplateSource source = null;
517 if (hasDocument(name))
518 {
519 source = new LocalFileSystemStoreTemplateSource(name);
520 }
521 return source;
522 }
523
524
525
526
527 public long getLastModified(Object templateSource)
528 {
529 return ((LocalFileSystemStoreTemplateSource) templateSource).lastModified();
530 }
531
532
533
534
535
536 public Reader getReader(Object templateSource, String encoding)
537 throws IOException
538 {
539 return ((LocalFileSystemStoreTemplateSource) templateSource).getReader(encoding);
540 }
541 }
542
543
544
545
546
547
548 private class LocalFileSystemStoreTemplateSource
549 {
550 private String templatePath;
551
552 private LocalFileSystemStoreTemplateSource(String path)
553 {
554 this.templatePath = path;
555 }
556
557 private long lastModified()
558 {
559 try
560 {
561 return LocalFileSystemStore.this.lastModified(templatePath);
562 }
563 catch (IOException e)
564 {
565 return -1;
566 }
567 }
568
569 private Reader getReader(String encoding) throws IOException
570 {
571 Reader reader = null;
572
573 File f = new File(toAbsolutePath(templatePath));
574 if (f.exists())
575 {
576 reader = new FileReader(f);
577 }
578
579 return reader;
580 }
581 }
582
583
584
585
586
587
588 private class LocalFileSystemStoreScriptContent implements ScriptContent
589 {
590 private String scriptPath;
591
592
593
594
595
596
597 private LocalFileSystemStoreScriptContent(String path)
598 {
599 this.scriptPath = path;
600 }
601
602
603
604
605 public String getPath()
606 {
607 return getBasePath() + '/' + this.scriptPath;
608 }
609
610
611
612
613 public String getPathDescription()
614 {
615 return getBasePath() + '/' + this.scriptPath;
616 }
617
618
619
620
621 public InputStream getInputStream()
622 {
623 InputStream is = null;
624
625 try
626 {
627 File f = new File(toAbsolutePath(scriptPath));
628 if (f.exists())
629 {
630 is = new FileInputStream(f);
631 }
632 }
633 catch (IOException e)
634 {
635 throw new PlatformRuntimeException(
636 "Unable to load script: " + scriptPath, e);
637 }
638
639 return is;
640 }
641
642
643
644
645 public Reader getReader()
646 {
647 Reader reader = null;
648
649 try
650 {
651 File f = new File(toAbsolutePath(scriptPath));
652 if (f.exists())
653 {
654 reader = new FileReader(f);
655 }
656 }
657 catch (IOException e)
658 {
659 throw new PlatformRuntimeException(
660 "Unable to load script: " + scriptPath, e);
661 }
662
663 return reader;
664 }
665
666
667
668
669 public boolean isSecure()
670 {
671 return false;
672 }
673
674
675
676
677 public boolean isCachable()
678 {
679 return false;
680 }
681 }
682
683 private class PatternFileFilter implements FileFilter
684 {
685 Pattern pattern;
686
687 public PatternFileFilter(String pat)
688 {
689 this.pattern = Pattern.compile(pat);
690 }
691
692 public boolean accept(File pathname)
693 {
694 boolean accept = false;
695
696 if (pathname.isDirectory())
697 {
698 accept = false;
699 }
700 else
701 {
702 String path = null;
703 try
704 {
705 path = pathname.toURL().toExternalForm();
706 if (path.endsWith("\\") || path.endsWith("/"))
707 {
708 path = path.substring(0, path.length() - 1);
709 }
710
711 accept = pattern.matcher(path).matches();
712 }
713 catch(MalformedURLException mue) { }
714 }
715
716 return accept;
717 }
718 }
719
720 private List<File> listPath(File path, FileFilter filter,
721 boolean listChildren)
722 {
723 List<File> results = new ArrayList<File>();
724
725 listPath(path, filter, results, listChildren);
726
727 return results;
728 }
729
730 private void listPath(File path, FileFilter filter, List<File> results,
731 boolean listChildren)
732 {
733
734 File files[] = path.listFiles(filter);
735 if (files.length > 0)
736 {
737
738 Arrays.sort(files);
739
740
741 for (int i = 0; i < files.length; i++)
742 {
743 results.add(files[i]);
744 }
745 }
746
747
748 if (listChildren)
749 {
750
751 files = path.listFiles();
752 for (int i = 0; i < files.length; i++)
753 {
754
755 if (files[i].isDirectory())
756 {
757
758 listPath(files[i], filter, results, listChildren);
759 }
760 }
761 }
762 }
763 }