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