1
2
3
4
5
6
7 package org.mule.util.queue;
8
9 import org.mule.api.MuleContext;
10 import org.mule.api.MuleException;
11 import org.mule.api.context.MuleContextAware;
12 import org.mule.api.transformer.wire.WireFormat;
13 import org.mule.transformer.wire.SerializationWireFormat;
14 import org.mule.util.FileUtils;
15 import org.mule.util.UUID;
16 import org.mule.util.file.DeleteException;
17
18 import java.io.File;
19 import java.io.FileInputStream;
20 import java.io.FileNotFoundException;
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.Arrays;
27 import java.util.List;
28
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31
32 public class FilePersistenceStrategy implements QueuePersistenceStrategy, MuleContextAware
33 {
34 private static final Log logger = LogFactory.getLog(FilePersistenceStrategy.class);
35
36
37 public static final String DEFAULT_QUEUE_STORE = "queuestore";
38
39 public static final String EXTENSION = ".msg";
40
41 private File store;
42
43 protected MuleContext muleContext;
44
45 private WireFormat serializer;
46
47 public FilePersistenceStrategy(WireFormat serializer)
48 {
49 super();
50 this.serializer = serializer;
51 }
52
53 public FilePersistenceStrategy()
54 {
55 this(new SerializationWireFormat());
56 }
57
58 public void setMuleContext(MuleContext context)
59 {
60 this.muleContext = context;
61
62 serializer.setMuleContext(muleContext);
63 }
64
65 public Object store(String queue, Object obj) throws IOException
66 {
67 String id = UUID.getUUID();
68
69 String filename = queue + File.separator + id + EXTENSION;
70 File file = FileUtils.newFile(store, filename);
71
72 if (!file.getParentFile().exists())
73 {
74 createStoreDirectory(file.getParentFile());
75 }
76
77 OutputStream out = new FileOutputStream(file);
78 try
79 {
80 serializer.write(out, obj, muleContext.getConfiguration().getDefaultEncoding());
81 }
82 catch (MuleException e)
83 {
84 IOException iox = new IOException();
85 iox.initCause(e);
86 throw iox;
87 }
88 finally
89 {
90 out.close();
91 }
92
93 return id;
94 }
95
96 protected synchronized void createStoreDirectory(File direcetory) throws IOException
97 {
98
99
100 if (!direcetory.exists() && !direcetory.mkdirs())
101 {
102 throw new IOException("Failed to create directory: " + direcetory.getAbsolutePath());
103 }
104 }
105
106 public void remove(String queue, Object id) throws IOException
107 {
108 String fileName = queue + File.separator + id + EXTENSION;
109 File file = FileUtils.newFile(store, fileName);
110 if (file.exists())
111 {
112 if (!file.delete())
113 {
114 throw new DeleteException(file);
115 }
116 }
117 else
118 {
119 throw new FileNotFoundException(file.getAbsolutePath());
120 }
121 }
122
123 public Object load(String queue, Object id) throws IOException
124 {
125 String fileName = queue + File.separator + id + EXTENSION;
126 File file = FileUtils.newFile(store, fileName);
127
128 InputStream in = new FileInputStream(file);
129 try
130 {
131 return serializer.read(in);
132 }
133 catch (MuleException e)
134 {
135 IOException iox = new IOException(e.getDetailedMessage());
136 iox.initCause(e);
137 throw iox;
138 }
139 finally
140 {
141 in.close();
142 }
143 }
144
145 public List<Holder> restore() throws IOException
146 {
147 List<Holder> msgs = new ArrayList<Holder>();
148 if (store == null)
149 {
150 logger.warn("No store has be set on the File Persistence Strategy. Not restoring at this time");
151 return msgs;
152 }
153
154 try
155 {
156 restoreFiles(store, msgs);
157
158 if (logger.isDebugEnabled())
159 {
160 logger.debug("Restore retrieved " + msgs.size() + " objects");
161 }
162
163 return msgs;
164 }
165 catch (ClassNotFoundException e)
166 {
167 throw (IOException) new IOException("Could not restore").initCause(e);
168 }
169 }
170
171 protected void restoreFiles(File dir, List<Holder> msgs) throws IOException, ClassNotFoundException
172 {
173 File[] files = dir.listFiles();
174 if (files == null)
175 {
176 return;
177 }
178
179
180 Arrays.sort(files);
181 for (int i = 0; i < files.length; i++)
182 {
183 if (files[i].isDirectory())
184 {
185 restoreFiles(files[i], msgs);
186 }
187 else if (files[i].getName().endsWith(EXTENSION))
188 {
189 if (files[i].length() == 0)
190 {
191 FileUtils.deleteQuietly(files[i]);
192 logger.debug("Removing zero size file: " + files[i].getAbsolutePath());
193 continue;
194 }
195
196 String id = files[i].getCanonicalPath();
197 id = id.substring(store.getCanonicalPath().length() + 1, id.length() - EXTENSION.length());
198 String queue = id.substring(0, id.indexOf(File.separator));
199 id = id.substring(queue.length() + 1);
200 msgs.add(new HolderImpl(queue, id));
201 }
202 }
203 }
204
205 public void open() throws IOException
206 {
207 String path = muleContext.getConfiguration().getWorkingDirectory() + File.separator + DEFAULT_QUEUE_STORE;
208 store = FileUtils.newFile(path).getCanonicalFile();
209 if (!store.exists())
210 {
211 createStoreDirectory(store);
212 }
213 }
214
215 public void close() throws IOException
216 {
217
218 }
219
220 protected static class HolderImpl implements Holder
221 {
222 private String queue;
223 private Object id;
224
225 public HolderImpl(String queue, Object id)
226 {
227 this.queue = queue;
228 this.id = id;
229 }
230
231 public Object getId()
232 {
233 return id;
234 }
235
236 public String getQueue()
237 {
238 return queue;
239 }
240 }
241
242 public boolean isTransient()
243 {
244 return false;
245 }
246 }