KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > snipsnap > snip > SnipSpaceImpl


1 /*
2  * This file is part of "SnipSnap Wiki/Weblog".
3  *
4  * Copyright (c) 2002 Stephan J. Schmidt, Matthias L. Jugel
5  * All Rights Reserved.
6  *
7  * Please visit http://snipsnap.org/ for updates and contact.
8  *
9  * --LICENSE NOTICE--
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  * --LICENSE NOTICE--
24  */

25
26 package org.snipsnap.snip;
27
28 import org.apache.lucene.search.Hits;
29 import org.codehaus.nanning.Aspects;
30 import org.radeox.util.logging.Logger;
31 import org.snipsnap.app.Application;
32 import org.snipsnap.app.ApplicationManager;
33 import org.snipsnap.app.ApplicationStorage;
34 import org.snipsnap.container.Components;
35 import org.snipsnap.notification.Message;
36 import org.snipsnap.notification.MessageService;
37 import org.snipsnap.snip.storage.CacheSnipStorage;
38 import org.snipsnap.snip.storage.CacheStorage;
39 import org.snipsnap.snip.storage.CacheableStorage;
40 import org.snipsnap.snip.storage.MemorySnipStorage;
41 import org.snipsnap.snip.storage.QuerySnipStorage;
42 import org.snipsnap.snip.storage.SnipStorage;
43 import org.snipsnap.user.Digest;
44 import org.snipsnap.util.ApplicationAwareMap;
45 import org.snipsnap.util.Queue;
46 import org.snipsnap.util.mail.PostDaemon;
47 import org.snipsnap.versioning.VersionManager;
48
49 import java.io.IOException JavaDoc;
50 import java.sql.Timestamp JavaDoc;
51 import java.util.ArrayList JavaDoc;
52 import java.util.HashMap JavaDoc;
53 import java.util.Iterator JavaDoc;
54 import java.util.List JavaDoc;
55 import java.util.ListIterator JavaDoc;
56 import java.util.Map JavaDoc;
57 import java.util.Timer JavaDoc;
58 import java.util.TimerTask JavaDoc;
59
60 /**
61  * SnipSpace implementation handles all the operations with snips like
62  * loading, storing, searching etc.
63  *
64  * TODO move indexing to Interceptor
65  * TODO move ETag / changed handling to Interceptor
66  * TODO move changed to Interceptor
67  *
68  * @author Stephan J. Schmidt F
69  * @version $Id: SnipSpaceImpl.java 1606 2004-05-17 10:56:18Z leo $
70  */

71
72 public class SnipSpaceImpl implements SnipSpace {
73   // List of snips that were changed
74
private ApplicationAwareMap changed;
75   private List JavaDoc delayed;
76
77   // List of snips that are scheduled for storage
78
private SnipIndexer indexer;
79   private Timer JavaDoc timer;
80   private String JavaDoc eTag;
81   private SnipStorage storage;
82   private VersionManager versionManager;
83
84   private ApplicationAwareMap blogs;
85
86   public SnipSpaceImpl(SnipStorage storage,
87                        ApplicationManager manager,
88                        VersionManager versionManager
89                        ) {
90     this.storage = storage;
91     this.versionManager = versionManager;
92
93     changed = new ApplicationAwareMap(HashMap JavaDoc.class, Queue.class);
94     blogs = new ApplicationAwareMap(HashMap JavaDoc.class, HashMap JavaDoc.class);
95
96     // @TODO resolve this with components from PicoContainer
97
// Fully fill the cache with all Snips
98
if ("full".equals(Application.get().getConfiguration().getCache())) {
99       Logger.debug("Cache strategy is: keep full, using MemorySnipStorage and QuerySnipStorage");
100       // If we keep all snips in memory we can use queries directly on the snip list
101
// Wrap the real storage with the memory storage wrapper and an in-memory
102
// query class
103
this.storage = new QuerySnipStorage(new MemorySnipStorage(storage, manager));
104     } else if ("cache".equals(Application.get().getConfiguration().getCache())
105         && storage instanceof CacheableStorage) {
106       Logger.debug("Cache strategy is: cache, using CacheSnipStorage");
107       // Otherwise at least wrap the persistence store
108
// with a cache that does not need to load and create objects
109
CacheableStorage old = (CacheableStorage) storage;
110       this.storage = new CacheSnipStorage(storage);
111       // We have to tell CacheStorage (JDBCSnipStorage) where to get
112
// it's cache from for checking
113
old.setCache(((CacheStorage) storage).getCache());
114     }
115
116     indexer = new SnipIndexer();
117
118     //This should also fill the cache
119
// This should be moved somewhere down, SnipSpace need not know about
120
// different applications
121
Iterator JavaDoc iterator = manager.getApplications().iterator();
122 // System.out.println("apps = "+manager.getApplications());
123
while (iterator.hasNext()) {
124       Map app = (Map) iterator.next();
125       String JavaDoc applicationOid = (String JavaDoc) app.get(ApplicationStorage.OID);
126       ((Queue) changed.getObject(applicationOid)).fill(this.storage.storageByRecent(applicationOid, 50));
127     }
128
129     // We do not store frequent changes right away but
130
// collect them in "delayed"
131
delayed = new ArrayList JavaDoc();
132
133     setETag();
134     timer = new Timer JavaDoc();
135     timer.schedule(new TimerTask JavaDoc() {
136
137       public void run() {
138         List JavaDoc toStoreList = delayed;
139         // Just to be sure: To be atomic we first create the list and
140
// then assign the list to delayed
141
// With help from french_c aka Jens
142
List JavaDoc temp = new ArrayList JavaDoc();
143         delayed = temp;
144
145         ListIterator JavaDoc iterator = toStoreList.listIterator();
146         while (iterator.hasNext()) {
147           Snip snip = (Snip) iterator.next();
148           // make sure the OID is set to the corresponding snips SnipSpace
149
Application.get().storeObject(Application.OID, snip.getApplication());
150           systemStore(snip);
151           iterator.remove();
152         }
153       }
154       // execute after 5 minutes and then
155
// every 5 minutes
156
}, 5 * 60 * 1000, 5 * 60 * 1000);
157
158     // start post daemon
159
PostDaemon.getInstance();
160   }
161
162   public void init() {
163   }
164
165   public String JavaDoc getETag() {
166     return "\"" + eTag + "\"";
167   }
168
169   public Blog getBlog() {
170     return getBlog(Application.get().getConfiguration().getStartSnip());
171   }
172
173   // Perhaps add getBlog(Snip)
174
public Blog getBlog(String JavaDoc name) {
175     Blog blog;
176     // ApplicationOid::name/this/is/snip
177
if (blogs.getMap().containsKey(name)) {
178       blog = (Blog) blogs.getMap().get(name);
179     } else {
180 // System.out.println("SnipSpace aspect="+Aspects.getThis());
181
// System.out.flush();
182
blog = (Blog) org.snipsnap.interceptor.Aspects.newInstance(
183           new BlogImpl((SnipSpace) Aspects.getThis(), name),
184           Blog.class);
185       blogs.getMap().put(name, blog);
186     }
187     return blog;
188   }
189
190   // A snip is changed by the user (created, stored)
191
public void changed(Snip snip) {
192     changed.getQueue().add(snip);
193     setETag();
194   }
195
196   public void setETag() {
197     eTag = Digest.getDigest(new java.util.Date JavaDoc().toString());
198   }
199
200   public int getSnipCount() {
201     return storage.storageCount();
202   }
203
204   public List JavaDoc getChanged() {
205     return getChanged(15);
206   }
207
208   public List JavaDoc getChanged(int count) {
209     return changed.getQueue().get(count);
210   }
211
212   public List JavaDoc getAll() {
213     return storage.storageAll();
214   }
215
216   public List JavaDoc getSince(Timestamp JavaDoc date) {
217     return storage.storageByDateSince(date);
218   }
219
220   public List JavaDoc getByDate(String JavaDoc nameSpace, String JavaDoc start, String JavaDoc end) {
221     return storage.storageByDateInName(nameSpace, start, end);
222   }
223
224   /**
225    * A list of Snips, ordered by "hotness", currently
226    * viewcount.
227    *
228    * @param count number of snips in the result
229    * @return List of snips, ordered by hotness
230    */

231   public List JavaDoc getHot(int count) {
232     return storage.storageByHotness(count);
233   }
234
235   public List JavaDoc getComments(Snip snip) {
236     return storage.storageByComments(snip);
237   }
238
239   public List JavaDoc getByUser(String JavaDoc login) {
240     return storage.storageByUser(login);
241   }
242
243   public List JavaDoc getChildren(Snip snip) {
244     return storage.storageByParent(snip);
245   }
246
247   public List JavaDoc getChildrenDateOrder(Snip snip, int count) {
248     return storage.storageByParentNameOrder(snip, count);
249   }
250
251   public List JavaDoc getChildrenModifiedOrder(Snip snip, int count) {
252     return storage.storageByParentModifiedOrder(snip, count);
253   }
254
255   public void reIndex() {
256     try {
257       indexer.deleteIndex();
258       List JavaDoc snips = getAll();
259       Iterator JavaDoc iterator = snips.iterator();
260       while (iterator.hasNext()) {
261         Snip snip = (Snip) iterator.next();
262         indexer.reIndex(snip);
263       }
264     } catch (IOException JavaDoc e) {
265       Logger.fatal("unable to re-index SnipSpace: ", e);
266       e.printStackTrace();
267     }
268   }
269
270   public Hits search(String JavaDoc queryString) {
271     return indexer.search(queryString);
272   }
273
274   public String JavaDoc getContent(String JavaDoc title, String JavaDoc content) {
275     return content = "1 " + title + " {anchor:" + title + "}\n" + content;
276   }
277
278   public boolean exists(String JavaDoc name) {
279     if (null == load(name)) {
280       return false;
281     } else {
282       return true;
283     }
284   }
285
286   public Snip[] match(String JavaDoc pattern) {
287     return storage.match(pattern);
288   }
289
290   public Snip[] match(String JavaDoc start, String JavaDoc end) {
291     return storage.match(start, end);
292   }
293
294   public Snip load(String JavaDoc name) {
295     return storage.storageLoad(name);
296   }
297
298   public void store(Snip snip) {
299     Application app = Application.get();
300     changed(snip);
301     snip.setMUser(app.getUser());
302     snip.setMTime(new Timestamp JavaDoc(new java.util.Date JavaDoc().getTime()));
303     synchronized (snip) {
304       snip.setVersion(snip.getVersion() + 1);
305     }
306     versionManager.storeVersion(snip);
307     systemStore(snip);
308     MessageService service = (MessageService) Components.getComponent(MessageService.class);
309     if (null != service) {
310       service.send(new Message(Message.SNIP_MODIFIED, snip));
311     }
312     return;
313   }
314
315   /**
316    * Method with with wich the system can store snips.
317    * This methode does not change the mTime, the mUser,
318    * reindex the snip or add the snip to the modified list
319    *
320    * @param snip The snip to store
321    */

322   public void systemStore(Snip snip) {
323     //Logger.debug("systemStore - "+snip.getName());
324
Application app = Application.get();
325     long start = app.start();
326     storage.storageStore(snip);
327     indexer.reIndex(snip);
328     app.stop(start, "systemStore - " + snip.getName());
329     return;
330   }
331
332
333   /**
334    * Delays the storage of a snip for some time. Some information
335    * in a snip are changeg every view. To not store a snip every
336    * time it is viewed, delay the store and wait until some changes
337    * are cummulated. Should only be used, when the loss of the
338    * changes is tolerable.
339    *
340    * @param snip Snip to delay for storage
341    */

342   public void delayedStore(Snip snip) {
343     //Logger.debug("delayedStore - "+snip.getName());
344
Logger.debug("delayedStore");
345     synchronized (delayed) {
346       if (!delayed.contains(snip)) {
347         delayed.add(snip);
348       }
349     }
350   }
351
352   public Snip create(String JavaDoc name, String JavaDoc content) {
353     name = name.trim();
354     Snip snip = storage.storageCreate(name, content);
355     versionManager.storeVersion(snip);
356     changed(snip);
357     indexer.index(snip);
358     MessageService service = (MessageService) Components.getComponent(MessageService.class);
359     if (null != service) {
360       service.send(new Message(Message.SNIP_CREATE, snip));
361     }
362     return snip;
363   }
364
365   public void remove(Snip snip) {
366     synchronized (delayed) {
367       delayed.remove(snip);
368     }
369     changed.getQueue().remove(snip);
370     storage.storageRemove(snip);
371     indexer.removeIndex(snip);
372     return;
373   }
374 }
Popular Tags