KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > struts > webapp > example2 > memory > MemoryUserDatabase


1 /*
2  * Copyright 1999-2002,2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17
18 package org.apache.struts.webapp.example2.memory;
19
20
21 import java.io.BufferedInputStream JavaDoc;
22 import java.io.File JavaDoc;
23 import java.io.FileInputStream JavaDoc;
24 import java.io.FileOutputStream JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.OutputStreamWriter JavaDoc;
27 import java.io.PrintWriter JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import org.apache.commons.digester.Digester;
30 import org.apache.commons.digester.ObjectCreationFactory;
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.apache.struts.webapp.example2.Subscription;
34 import org.apache.struts.webapp.example2.User;
35 import org.apache.struts.webapp.example2.UserDatabase;
36 import org.xml.sax.Attributes JavaDoc;
37
38
39 /**
40  * <p>Concrete implementation of {@link UserDatabase} for an in-memory
41  * database backed by an XML data file.</p>
42  *
43  * @author Craig R. McClanahan
44  * @version $Rev: 54934 $ $Date: 2004-10-16 18:07:50 +0100 (Sat, 16 Oct 2004) $
45  * @since Struts 1.1
46  */

47
48 public final class MemoryUserDatabase implements UserDatabase {
49
50
51     // ----------------------------------------------------------- Constructors
52

53
54     // ----------------------------------------------------- Instance Variables
55

56
57     /**
58      * Logging output for this user database instance.
59      */

60     private Log log = LogFactory.getLog(this.getClass());
61
62
63     /**
64      * The {@link User}s associated with this UserDatabase, keyed by username.
65      */

66     private HashMap JavaDoc users = new HashMap JavaDoc();
67
68
69     // ------------------------------------------------------------- Properties
70

71
72     /**
73      * Absolute pathname to the persistent file we use for loading and storing
74      * persistent data.
75      */

76     private String JavaDoc pathname = null;
77
78     private String JavaDoc pathnameOld = null;
79
80     private String JavaDoc pathnameNew = null;
81
82     public String JavaDoc getPathname() {
83         return (this.pathname);
84     }
85
86     public void setPathname(String JavaDoc pathname) {
87         this.pathname = pathname;
88         pathnameOld = pathname + ".old";
89         pathnameNew = pathname + ".new";
90     }
91
92
93     // --------------------------------------------------------- Public Methods
94

95
96     /**
97      * <p>Finalize access to the underlying persistence layer.</p>
98      *
99      * @exception Exception if a database access error occurs
100      */

101     public void close() throws Exception JavaDoc {
102
103         save();
104
105     }
106
107
108     /**
109      * <p>Create and return a new {@link User} defined in this user database.
110      * </p>
111      *
112      * @param username Username of the new user
113      *
114      * @exception IllegalArgumentExceptionif the specified username
115      * is not unique
116      */

117     public User createUser(String JavaDoc username) {
118
119         synchronized (users) {
120             if (users.get(username) != null) {
121                 throw new IllegalArgumentException JavaDoc("Duplicate user '" +
122                                                    username + "'");
123             }
124             if (log.isTraceEnabled()) {
125                 log.trace("Creating user '" + username + "'");
126             }
127             MemoryUser user = new MemoryUser(this, username);
128             synchronized (users) {
129                 users.put(username, user);
130             }
131             return (user);
132         }
133
134     }
135
136
137     /**
138      * <p>Return the existing {@link User} with the specified username,
139      * if any; otherwise return <code>null</code>.</p>
140      *
141      * @param username Username of the user to retrieve
142      */

143     public User findUser(String JavaDoc username) {
144
145         synchronized (users) {
146             return ((User) users.get(username));
147         }
148
149     }
150
151
152     /**
153      * <p>Return the set of {@link User}s defined in this user database.</p>
154      */

155     public User[] findUsers() {
156
157         synchronized (users) {
158             User results[] = new User[users.size()];
159             return ((User[]) users.values().toArray(results));
160         }
161
162     }
163
164
165     /**
166      * <p>Initiate access to the underlying persistence layer.</p>
167      *
168      * @exception Exception if a database access error occurs
169      */

170     public void open() throws Exception JavaDoc {
171
172         FileInputStream JavaDoc fis = null;
173         BufferedInputStream JavaDoc bis = null;
174
175         try {
176
177             // Acquire an input stream to our database file
178
if (log.isDebugEnabled()) {
179                 log.debug("Loading database from '" + pathname + "'");
180             }
181             fis = new FileInputStream JavaDoc(pathname);
182             bis = new BufferedInputStream JavaDoc(fis);
183
184             // Construct a digester to use for parsing
185
Digester digester = new Digester();
186             digester.push(this);
187             digester.setValidating(false);
188             digester.addFactoryCreate
189                 ("database/user",
190                  new MemoryUserCreationFactory(this));
191             digester.addFactoryCreate
192                 ("database/user/subscription",
193                  new MemorySubscriptionCreationFactory(this));
194
195             // Parse the input stream to initialize our database
196
digester.parse(bis);
197             bis.close();
198             bis = null;
199             fis = null;
200
201         } catch (Exception JavaDoc e) {
202
203             log.error("Loading database from '" + pathname + "':", e);
204             throw e;
205
206         } finally {
207
208             if (bis != null) {
209                 try {
210                     bis.close();
211                 } catch (Throwable JavaDoc t) {
212                     ;
213                 }
214                 bis = null;
215                 fis = null;
216             }
217
218         }
219
220     }
221
222
223     /**
224      * Remove the specified {@link User} from this database.
225      *
226      * @param user User to be removed
227      *
228      * @exception IllegalArgumentException if the specified user is not
229      * associated with this database
230      */

231     public void removeUser(User user) {
232
233         if (!(this == user.getDatabase())) {
234             throw new IllegalArgumentException JavaDoc
235                 ("User not associated with this database");
236         }
237         if (log.isTraceEnabled()) {
238             log.trace("Removing user '" + user.getUsername() + "'");
239         }
240         synchronized (users) {
241             users.remove(user.getUsername());
242         }
243
244     }
245
246
247     /**
248      * <p>Save any pending changes to the underlying persistence layer.</p>
249      *
250      * @exception Exception if a database access error occurs
251      */

252     public void save() throws Exception JavaDoc {
253
254         if (log.isDebugEnabled()) {
255             log.debug("Saving database to '" + pathname + "'");
256         }
257         File JavaDoc fileNew = new File JavaDoc(pathnameNew);
258         PrintWriter JavaDoc writer = null;
259
260         try {
261
262             // Configure our PrintWriter
263
FileOutputStream JavaDoc fos = new FileOutputStream JavaDoc(fileNew);
264             OutputStreamWriter JavaDoc osw = new OutputStreamWriter JavaDoc(fos);
265             writer = new PrintWriter JavaDoc(osw);
266
267             // Print the file prolog
268
writer.println("<?xml version='1.0'?>");
269             writer.println("<database>");
270
271             // Print entries for each defined user and associated subscriptions
272
User users[] = findUsers();
273             for (int i = 0; i < users.length; i++) {
274                 writer.print(" ");
275                 writer.println(users[i]);
276                 Subscription subscriptions[] =
277                     users[i].getSubscriptions();
278                 for (int j = 0; j < subscriptions.length; j++) {
279                     writer.print(" ");
280                     writer.println(subscriptions[j]);
281                     writer.print(" ");
282                     writer.println("</subscription>");
283                 }
284                 writer.print(" ");
285                 writer.println("</user>");
286             }
287
288             // Print the file epilog
289
writer.println("</database>");
290
291             // Check for errors that occurred while printing
292
if (writer.checkError()) {
293                 writer.close();
294                 fileNew.delete();
295                 throw new IOException JavaDoc
296                     ("Saving database to '" + pathname + "'");
297             }
298             writer.close();
299             writer = null;
300
301         } catch (IOException JavaDoc e) {
302
303             if (writer != null) {
304                 writer.close();
305             }
306             fileNew.delete();
307             throw e;
308
309         }
310
311
312         // Perform the required renames to permanently save this file
313
File JavaDoc fileOrig = new File JavaDoc(pathname);
314         File JavaDoc fileOld = new File JavaDoc(pathnameOld);
315         if (fileOrig.exists()) {
316             fileOld.delete();
317             if (!fileOrig.renameTo(fileOld)) {
318                 throw new IOException JavaDoc
319                     ("Renaming '" + pathname + "' to '" + pathnameOld + "'");
320             }
321         }
322         if (!fileNew.renameTo(fileOrig)) {
323             if (fileOld.exists()) {
324                 fileOld.renameTo(fileOrig);
325             }
326             throw new IOException JavaDoc
327                 ("Renaming '" + pathnameNew + "' to '" + pathname + "'");
328         }
329         fileOld.delete();
330
331     }
332
333
334 }
335
336
337 /**
338  * Digester object creation factory for subscription instances.
339  */

340 class MemorySubscriptionCreationFactory implements ObjectCreationFactory {
341
342     public MemorySubscriptionCreationFactory(MemoryUserDatabase database) {
343         this.database = database;
344     }
345
346     private MemoryUserDatabase database = null;
347
348     private Digester digester = null;
349
350     public Digester getDigester() {
351         return (this.digester);
352     }
353
354     public void setDigester(Digester digester) {
355         this.digester = digester;
356     }
357
358     public Object JavaDoc createObject(Attributes JavaDoc attributes) {
359         String JavaDoc host = attributes.getValue("host");
360         User user = (User) digester.peek();
361         Subscription subscription = user.createSubscription(host);
362         String JavaDoc autoConnect = attributes.getValue("autoConnect");
363         if (autoConnect == null) {
364             autoConnect = "false";
365         }
366         if ("true".equalsIgnoreCase(autoConnect) ||
367             "yes".equalsIgnoreCase(autoConnect)) {
368             subscription.setAutoConnect(true);
369         } else {
370             subscription.setAutoConnect(false);
371         }
372         subscription.setPassword(attributes.getValue("password"));
373         subscription.setType(attributes.getValue("type"));
374         subscription.setUsername(attributes.getValue("username"));
375         return (subscription);
376     }
377
378 }
379
380
381 /**
382  * Digester object creation factory for user instances.
383  */

384 class MemoryUserCreationFactory implements ObjectCreationFactory {
385
386     public MemoryUserCreationFactory(MemoryUserDatabase database) {
387         this.database = database;
388     }
389
390     private MemoryUserDatabase database = null;
391
392     private Digester digester = null;
393
394     public Digester getDigester() {
395         return (this.digester);
396     }
397
398     public void setDigester(Digester digester) {
399         this.digester = digester;
400     }
401
402     public Object JavaDoc createObject(Attributes JavaDoc attributes) {
403         String JavaDoc username = attributes.getValue("username");
404         User user = database.createUser(username);
405         user.setFromAddress(attributes.getValue("fromAddress"));
406         user.setFullName(attributes.getValue("fullName"));
407         user.setPassword(attributes.getValue("password"));
408         user.setReplyToAddress(attributes.getValue("replyToAddress"));
409         return (user);
410     }
411
412 }
413
Popular Tags