1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.springframework.batch.admin.service;
17
18 import org.apache.commons.io.FileUtils;
19 import org.apache.commons.logging.Log;
20 import org.apache.commons.logging.LogFactory;
21 import org.springframework.beans.factory.InitializingBean;
22 import org.springframework.context.ResourceLoaderAware;
23 import org.springframework.core.io.ContextResource;
24 import org.springframework.core.io.DefaultResourceLoader;
25 import org.springframework.core.io.FileSystemResource;
26 import org.springframework.core.io.Resource;
27 import org.springframework.core.io.ResourceLoader;
28 import org.springframework.core.io.support.ResourcePatternResolver;
29 import org.springframework.core.io.support.ResourcePatternUtils;
30 import org.springframework.util.Assert;
31
32 import java.io.File;
33 import java.io.IOException;
34 import java.util.ArrayList;
35 import java.util.Arrays;
36 import java.util.Collections;
37 import java.util.List;
38
39
40
41
42
43
44
45
46
47 public class LocalFileService implements FileService, InitializingBean, ResourceLoaderAware {
48
49 private File outputDir = new File(System.getProperty("java.io.tmpdir", "/tmp"), "batch/files");
50
51 private static final Log logger = LogFactory.getLog(LocalFileService.class);
52
53 private ResourceLoader resourceLoader = new DefaultResourceLoader();
54
55 private FileSender fileSender;
56
57 public void setResourceLoader(ResourceLoader resourceLoader) {
58 this.resourceLoader = resourceLoader;
59 }
60
61 public void setFileSender(FileSender fileSender) {
62 this.fileSender = fileSender;
63 }
64
65
66
67
68
69
70 public void setOutputDir(File outputDir) {
71 this.outputDir = outputDir;
72 }
73
74 public void afterPropertiesSet() throws Exception {
75 Assert.state(fileSender != null, "A FileSender must be provided");
76 if (!outputDir.exists()) {
77 Assert.state(outputDir.mkdirs(), "Cannot create output directory " + outputDir);
78 }
79 Assert.state(outputDir.exists(), "Output directory does not exist " + outputDir);
80 Assert.state(outputDir.isDirectory(), "Output file is not a directory " + outputDir);
81 }
82
83 public FileInfo createFile(String path) throws IOException {
84
85 path = sanitize(path);
86
87 Assert.hasText(path, "The file path must not be empty");
88
89 String name = path.substring(path.lastIndexOf("/") + 1);
90 String parent = path.substring(0, path.lastIndexOf(name));
91 if (parent.endsWith("/")) {
92 parent = parent.substring(0, parent.length() - 1);
93 }
94
95 File directory = new File(outputDir, parent);
96 directory.mkdirs();
97 Assert.state(directory.exists() && directory.isDirectory(), "Could not create directory: " + directory);
98
99 FileInfo result = new FileInfo(path);
100 File dest = new File(outputDir, result.getFileName());
101 dest.createNewFile();
102
103 return result;
104
105 }
106
107
108
109
110
111 private String extractPath(File target) {
112 String outputPath = outputDir.getAbsolutePath();
113 return target.getAbsolutePath().substring(outputPath.length() + 1).replace("\\", "/");
114 }
115
116 public boolean publish(FileInfo dest) throws IOException {
117 String path = dest.getPath();
118 fileSender.send(getResource(path).getFile());
119 return true;
120 }
121
122 public int countFiles() {
123 ResourcePatternResolver resolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
124 Resource[] resources;
125 try {
126 resources = resolver.getResources("file:///" + outputDir.getAbsolutePath() + "/**");
127 }
128 catch (IOException e) {
129 throw new IllegalStateException("Unexpected problem resolving files", e);
130 }
131 return resources.length;
132 }
133
134 public List<FileInfo> getFiles(int startFile, int pageSize) throws IOException {
135
136 List<FileInfo> files = getFiles("**");
137
138 String path = "";
139 int count = 0;
140 for (FileInfo info : files) {
141 FileInfo shortInfo = info.shortPath();
142 if (!path.equals(shortInfo.getPath())) {
143 files.set(count, shortInfo);
144 path = shortInfo.getPath();
145 }
146 count++;
147 }
148
149 return new ArrayList<FileInfo>(files.subList(startFile, Math.min(startFile + pageSize, files.size())));
150
151 }
152
153 private List<FileInfo> getFiles(String pattern) {
154 ResourcePatternResolver resolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
155 List<Resource> resources = new ArrayList<Resource>();
156
157 if (!pattern.startsWith("/")) {
158 pattern = "/" + outputDir.getAbsolutePath() + "/" + pattern;
159 }
160 if (!pattern.startsWith("file:")) {
161 pattern = "file:///" + pattern;
162 }
163
164 try {
165 resources = Arrays.asList(resolver.getResources(pattern));
166 }
167 catch (IOException e) {
168 logger.debug("Cannot locate files " + pattern, e);
169 return new ArrayList<FileInfo>();
170 }
171
172 List<FileInfo> files = new ArrayList<FileInfo>();
173 for (Resource resource : resources) {
174 File file;
175 try {
176 file = resource.getFile();
177 if (file.isFile()) {
178 FileInfo info = new FileInfo(extractPath(file));
179 files.add(info);
180 }
181 }
182 catch (IOException e) {
183 logger.debug("Cannot locate file " + resource, e);
184 }
185 }
186
187 Collections.sort(files);
188 return new ArrayList<FileInfo>(files);
189
190 }
191
192 public int delete(String pattern) throws IOException {
193
194 ResourcePatternResolver resolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
195 if (!pattern.startsWith("/")) {
196 pattern = "/" + outputDir.getAbsolutePath() + "/" + pattern;
197 }
198 if (!pattern.startsWith("file:")) {
199 pattern = "file:///" + pattern;
200 }
201
202 Resource[] resources = resolver.getResources(pattern);
203
204 int count = 0;
205 for (Resource resource : resources) {
206 File file = resource.getFile();
207 if (file.isFile()) {
208 count++;
209 FileUtils.deleteQuietly(file);
210 }
211 }
212
213 return count;
214
215 }
216
217 public Resource getResource(String path) {
218
219 path = sanitize(path);
220 FileInfo pattern = new FileInfo(path);
221 List<FileInfo> files = getFiles(pattern.getPattern());
222 FileInfo info = files.isEmpty() ? pattern : files.get(0);
223 File file = new File(outputDir, info.getFileName());
224 return new FileServiceResource(file, path);
225
226 }
227
228 public File getUploadDirectory() {
229 return outputDir;
230 }
231
232
233
234
235
236
237
238
239 private String sanitize(String path) {
240 path = path.replace("\\", "/");
241 if (path.startsWith("files:")) {
242 path = path.substring("files:".length());
243 while (path.startsWith("/")) {
244 path = path.substring(1);
245 }
246 }
247 return path;
248 }
249
250 private static class FileServiceResource extends FileSystemResource implements ContextResource {
251
252 private final String path;
253
254 public FileServiceResource(File file, String path) {
255 super(file);
256 this.path = path;
257 }
258
259 public String getPathWithinContext() {
260 return path;
261 }
262
263 }
264
265 }