1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.transaction.file;
18
19 import java.io.File;
20 import java.io.FileInputStream;
21 import java.io.FileOutputStream;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.OutputStream;
25 import java.util.ArrayList;
26 import java.util.List;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.commons.transaction.TransactionException;
31 import org.apache.commons.transaction.resource.ResourceException;
32 import org.apache.commons.transaction.resource.ResourceManager;
33 import org.apache.commons.transaction.resource.StreamableResource;
34 import org.apache.commons.transaction.util.FileHelper;
35
36 /**
37 * Default file system implementation of a
38 * {@link ResourceManager resource manager}.
39 *
40 * <p>
41 * Only two {@link StreamableResource#getProperty(String) properties} are
42 * supported for reading: "lastModified" and "length" . None are supported for
43 * {@link StreamableResource#setProperty(String, Object) setting} or
44 * {@link StreamableResource#readLock() removing}.
45 *
46 * <p>
47 * This implementation is <b>NOT</b> <em>thread-safe</em>. Use
48 * {@link TxFileResourceManager} if you require a <em>thread-safe</em>
49 * implementation.
50 */
51 public class FileResourceManager implements ResourceManager<FileResourceManager.FileResource> {
52
53 private Log logger = LogFactory.getLog(getClass());
54
55 protected String rootPath;
56
57 public FileResourceManager(String rootPath) {
58 try {
59 File file = new File(rootPath);
60 file.mkdirs();
61 this.rootPath = file.getCanonicalPath();
62 } catch (IOException e) {
63 throw new TransactionException(e);
64 }
65 }
66
67 public FileResourceManager.FileResource getResource(String path) throws ResourceException {
68 return new FileResource(path);
69 }
70
71 public String getRootPath() {
72 return rootPath;
73 }
74
75 protected static class FileResource implements StreamableResource {
76
77 private final File file;
78
79 private final String canonicalPath;
80
81 private final String name;
82
83 protected static File getFileForResource(StreamableResource resource)
84 throws ResourceException {
85 if (!(resource instanceof FileResource)) {
86 throw new ResourceException(
87 "Destination must be of created by FileResourceManager only!");
88
89 }
90 return ((FileResource) resource).getFile();
91 }
92
93 public FileResource(String path) throws ResourceException {
94 this(new File(path.trim()));
95 }
96
97 public FileResource(File file) throws ResourceException {
98 this.file = file;
99 try {
100 this.canonicalPath = file.getCanonicalPath();
101 } catch (IOException e) {
102 throw new ResourceException(e);
103 }
104 this.name = file.getName();
105 }
106
107 public void createAsDirectory() throws ResourceException {
108 if (!file.exists() && !file.mkdirs()) {
109 throw new ResourceException(ResourceException.Code.COULD_NOT_CREATE,
110 "Could not create directory");
111 }
112
113 }
114
115 public void createAsFile() throws ResourceException {
116 try {
117 if (!file.createNewFile()) {
118 throw new ResourceException(ResourceException.Code.COULD_NOT_CREATE,
119 "Could not create file");
120 }
121 } catch (IOException e) {
122 throw new ResourceException(e);
123 }
124 }
125
126 public void delete() throws ResourceException {
127 if (exists()) {
128 if (!isDirectory()) {
129 if (!getFile().delete())
130 throw new ResourceException(ResourceException.Code.COULD_NOT_DELETE,
131 "Could not create file");
132 } else {
133 FileHelper.removeRecursive(getFile());
134 }
135 }
136 }
137
138 public boolean exists() {
139 return file.exists();
140 }
141
142 public List<? extends FileResource> getChildren() throws ResourceException {
143 List<FileResource> result = new ArrayList<FileResource>();
144 File[] files = file.listFiles();
145 for (File file : files) {
146 result.add(create(file));
147 }
148 return result;
149 }
150
151 public FileResource getParent() throws ResourceException {
152
153
154
155
156
157 File parent = file.getParentFile();
158 if (parent == null)
159 return null;
160 return create(parent);
161 }
162
163 public String getPath() {
164 return canonicalPath;
165 }
166
167 public boolean isDirectory() {
168 return file.isDirectory();
169 }
170
171 public boolean isFile() {
172 return file.isFile();
173 }
174
175 public void move(StreamableResource destination) throws ResourceException {
176 if (!prepareMoveorCopy(destination))
177 moveOrCopySaneCheck(destination);
178 try {
179 if (isFile()) {
180 FileHelper.move(file, getFileForResource(destination));
181 } else {
182 FileHelper.moveRecursive(file, getFileForResource(destination));
183 }
184 } catch (IOException e) {
185 throw new ResourceException(e);
186 }
187 }
188
189 public void copy(StreamableResource destination) throws ResourceException {
190 if (!prepareMoveorCopy(destination))
191 moveOrCopySaneCheck(destination);
192 try {
193 if (isFile()) {
194 FileHelper.copy(file, getFileForResource(destination));
195 } else {
196 FileHelper.copyRecursive(file, getFileForResource(destination));
197 }
198 } catch (IOException e) {
199 throw new ResourceException(e);
200 }
201 }
202
203 protected boolean prepareMoveorCopy(StreamableResource destination)
204 throws ResourceException {
205 if (!destination.exists()) {
206 if (isDirectory()) {
207 destination.createAsDirectory();
208 } else {
209 destination.createAsFile();
210 }
211 return true;
212 }
213 return false;
214 }
215
216 protected void moveOrCopySaneCheck(StreamableResource destination) throws ResourceException {
217
218 File from = getFile();
219 File to = getFileForResource(destination);
220 if (!from.isDirectory()) {
221 if (to.isDirectory()) {
222 throw new ResourceException(ResourceException.Code.CANT_MOVE_OR_COPY,
223 "Could not move file to directory");
224 }
225
226 } else if (from.isDirectory()) {
227 if (to.isFile()) {
228 throw new ResourceException(ResourceException.Code.CANT_MOVE_OR_COPY,
229 "Could not move directory to file");
230 }
231 }
232 }
233
234 public InputStream readStream() throws ResourceException {
235 try {
236 FileInputStream is = new FileInputStream(file);
237 return is;
238 } catch (IOException e) {
239 throw new ResourceException(e);
240 }
241 }
242
243 public OutputStream writeStream(boolean append) throws ResourceException {
244 try {
245 FileOutputStream os = new FileOutputStream(file, append);
246 return os;
247 } catch (IOException e) {
248 throw new ResourceException(e);
249 }
250 }
251
252 public void removeProperty(String name) {
253 throw new UnsupportedOperationException("You can not remove properties from files!");
254 }
255
256 public void setProperty(String name, Object newValue) {
257 throw new UnsupportedOperationException("You can not set properties on files!");
258 }
259
260 public Object getProperty(String name) {
261 if (name.equals("lastModified")) {
262 return file.lastModified();
263 }
264 if (name.equals("length")) {
265 return file.length();
266 }
267 return null;
268 }
269
270
271
272 public void readLock() {
273 }
274
275
276
277 public void writeLock() {
278 }
279
280 protected File getFile() {
281 return file;
282 }
283
284 protected FileResource create(File file) throws ResourceException {
285 return new FileResource(file);
286 }
287
288 public FileResource getChild(String name) throws ResourceException {
289 File child = new File(file, name);
290 return create(child);
291 }
292
293 public String getName() {
294 return name;
295 }
296
297 }
298 }