KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > openedit > page > manage > PageManager


1 /*
2  Copyright (c) 2003 eInnovation Inc. All rights reserved
3
4  This library is free software; you can redistribute it and/or modify it under the terms
5  of the GNU Lesser General Public License as published by the Free Software Foundation;
6  either version 2.1 of the License, or (at your option) any later version.
7
8  This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10  See the GNU Lesser General Public License for more details.
11  */

12
13 package com.openedit.page.manage;
14
15 import java.util.HashMap JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.List JavaDoc;
18 import java.util.Map JavaDoc;
19
20 import org.apache.commons.collections.map.ReferenceMap;
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.openedit.repository.ContentItem;
24 import org.openedit.repository.Repository;
25 import org.openedit.repository.RepositoryException;
26 import org.openedit.repository.filesystem.StringItem;
27
28 import com.openedit.OpenEditException;
29 import com.openedit.PageAccessListener;
30 import com.openedit.WebPageRequest;
31 import com.openedit.page.Page;
32 import com.openedit.page.PageSettings;
33 import com.openedit.users.User;
34 import com.openedit.util.PathUtilities;
35
36 /**
37  * The PageManager is a central access point for locating pages. Pages are
38  * loaded and cached automatically. The cache will check the file's last
39  * modification time and will update if the stored time does not match the file
40  * system's time.
41  *
42  * @author Matt Avery, mavery@einnovation.com
43  */

44 public class PageManager
45 {
46     private static Log log = LogFactory.getLog( PageManager.class );
47
48     protected Map JavaDoc fieldPageAccessListeners;
49     protected Map JavaDoc fieldCache;
50     protected Repository fieldRepository;
51     protected PageSettingsManager fieldSettingsManager;
52
53     public PageManager()
54     {
55         log.debug("create page manager instance");
56     }
57     public Page getPage(String JavaDoc inPath, WebPageRequest inReq) throws OpenEditException
58     {
59         //this gets the page for this user
60
Page real = getPage(inPath);
61         return getPage(real,inReq);
62     }
63     /**
64      * This checks for pages in this order:
65      * 1. Draft page in the language directory
66      * 2. Page in the language directory
67      * 3. Draft in the real directory
68      * 4. Original file in the real directory
69      * @param inPage
70      * @param inReq
71      * @return
72      * @throws OpenEditException
73      */

74     
75     public Page getPage(Page inPage, WebPageRequest inReq) throws OpenEditException
76     {
77         boolean useDraft = true;
78         User user = inReq.getUser();
79         if ( user == null )
80         {
81             useDraft = false;
82         }
83
84         if ( useDraft && !user.hasProperty("oe.edit.draftmode") )
85         {
86             useDraft = false;
87         }
88         if( useDraft && inPage.isDraft() )
89         {
90             useDraft = false;
91         }
92         if( useDraft )
93         {
94             String JavaDoc draftedits = inPage.get("oe.edit.draftedits"); //This is the opposite of oe.edit.directedits
95
if ( draftedits != null && !Boolean.parseBoolean(draftedits) )
96             {
97                 useDraft = false;
98             }
99         }
100         boolean multipleLang = true;
101         String JavaDoc savein = inReq.getPageProperty("usemultiplelanguages");
102         if ( savein != null )
103         {
104             multipleLang = Boolean.parseBoolean(savein);
105         }
106         else
107         {
108             multipleLang = false;
109         }
110         String JavaDoc selectedcode = inReq.getLanguage();
111         String JavaDoc rootdir = "/translations/" + selectedcode;
112         if( multipleLang )
113         {
114             if( selectedcode == null || selectedcode.equals("default") || inPage.getPath().startsWith(rootdir) )
115             {
116                 multipleLang = false;
117             }
118         }
119         Page foundPage = null;
120         if ( useDraft)
121         {
122             String JavaDoc dp = PathUtilities.createDraftPath(inPage.getPath() );
123             if( multipleLang )
124             {
125                     Page translated = getPage( rootdir + dp);
126                     if( translated.exists() )
127                     {
128                         foundPage = translated;
129                     }
130                     else
131                     {
132                         translated = getPage( rootdir + inPage.getPath());
133                         if( translated.exists() )
134                         {
135                             foundPage = translated;
136                         }
137                     }
138             }
139             if( foundPage == null )
140             {
141                 Page draft = getPage(dp);
142                 if( draft.exists() )
143                 {
144                     foundPage = draft;
145                 }
146             }
147         }
148         else if( multipleLang )
149         {
150             Page translated = getPage( rootdir + inPage.getPath());
151             if( translated.exists() )
152             {
153                 foundPage = translated;
154             }
155         }
156         if( foundPage == null)
157         {
158             return inPage;
159         }
160         else
161         {
162             return foundPage;
163         }
164     }
165     
166     /**
167      * Get a Page instance from the given path. If no page can be found then
168      * this method will throw a FileNotFoundException.
169      *
170      * TODO: This method needs to be smarter. If I request page.html and I have
171      * content page.xml, I still need to return a Page object with both
172      * requested mime-type (text/html) and content mime-type (text/xml)
173      *
174      * @param path
175      * The page path
176      *
177      * @return The Page
178      *
179      * @throws OpenEditException
180      * Any Exception
181      */

182     public Page getPage( String JavaDoc inPath ) throws OpenEditException
183     {
184         if ( inPath == null)
185         {
186             return null;
187         }
188         String JavaDoc fullPath = PathUtilities.buildRelative( inPath, "/" );
189         
190         Page page = (Page) getCache().get( fullPath );
191         boolean reloadPage = false;
192         if ( page != null )
193         {
194                 if ( originalPathChanged(page) )
195                 {
196                     //if the fullpath alternative has been added then we need to blow away this page and its settings
197
reloadPage = true;
198                 }
199                 else if ( page.isCurrent() )
200                 {
201                     firePageRequested( page );
202                     return page;
203                 }
204         }
205         synchronized( getCache() )
206         { //lock down the config until we can configure the thing
207
page = (Page) getCache().get( fullPath );
208             if ( page == null || reloadPage || !page.isCurrent() ) //check for other threads that where waiting
209
{
210                 if ( reloadPage)
211                 {
212                     getPageSettingsManager().clearCache(fullPath);
213                 }
214                 page = createPage( fullPath );
215                 getCache().put( fullPath, page );
216                 firePageRequested( page );
217             }
218         }
219         return page;
220     }
221
222     private boolean originalPathChanged(Page inPage) throws OpenEditException
223     {
224         //we only need to check for changes when we are using an alternative content path
225
if( inPage.getAlternateContentPath() != null)
226         {
227             //go check the original path to make sure it has not appeared or been removed
228
boolean doesExist = getRepository().doesExist( inPage.getPath() );
229             boolean changed = (doesExist != inPage.isOriginalyExistedContentPath() );
230             return changed;
231         }
232         return false;
233     }
234
235     protected Page createPage( String JavaDoc inPath ) throws OpenEditException
236     {
237         PageSettings settings = getPageSettingsManager().getPageSettings( inPath );
238         Page page = new Page( inPath, settings );
239         populatePage( page );
240         return page;
241     }
242
243     protected void populatePage( Page inPage ) throws OpenEditException
244     {
245         String JavaDoc path = inPage.getPath();
246         ContentItem revision = getContentRevision( inPage );
247         inPage.setContentItem( revision );
248     }
249
250     protected ContentItem getContentRevision( Page inPage ) throws RepositoryException
251     {
252         String JavaDoc path = inPage.getPath();
253         if (inPage.getAlternateContentPath() != null)
254         {
255             //mark if this exist so the cache can be flushed if its added
256
inPage.setOriginalyExistedContentPath(getRepository().doesExist(path));
257             path = inPage.getAlternateContentPath();
258         }
259         ContentItem revision = getRepository().get( path );
260         if ( !revision.exists() )
261         {
262             //try looking for an XML file of the same name
263
String JavaDoc xmlPath = PathUtilities.extractPagePath( path )+ ".xml";
264             ContentItem alternateRevision = getRepository().get( xmlPath );
265             if( alternateRevision.exists() )
266             {
267                 revision = alternateRevision;
268             }
269         }
270         return revision;
271     }
272     
273     public PageSettingsManager getPageSettingsManager()
274     {
275         return fieldSettingsManager;
276     }
277     public void setPageSettingsManager( PageSettingsManager inManager)
278     {
279         fieldSettingsManager = inManager;
280     }
281
282     public void copyPage( Page inSourcePage, Page inDestinationPage ) throws RepositoryException
283     {
284         if (inSourcePage.exists())
285         {
286             String JavaDoc makeversion = inDestinationPage.getProperty("makeversion");
287             if (makeversion != null)
288             {
289                 boolean ver = Boolean.parseBoolean(makeversion);
290                 inDestinationPage.getContentItem().setMakeVersion(ver);
291             }
292
293             getRepository().copy( inSourcePage.getContentItem(), inDestinationPage.getContentItem() );
294         }
295         else
296         {
297             throw new RepositoryException("No such page to copy " + inSourcePage);
298         }
299         //If we take xconfs when we copy the we best keep the contentfile set
300
/* if (inSourcePage.getPageSettings().exists())
301         {
302             //TODO: Flatten down xconf a little
303             getRepository().copy( inSourcePage.getPageSettings().getXConf(),
304                     inDestinationPage.getPageSettings().getXConf() );
305             //
306         }
307 */
firePageAdded( inDestinationPage );
308     }
309
310     public void movePage( Page inSource, Page inDestination ) throws RepositoryException
311     {
312         if (inSource.exists())
313         {
314             getRepository().move( inSource.getContentItem(), inDestination.getContentItem() );
315         }
316         else
317         {
318             throw new RepositoryException("No such page to move " + inSource);
319         }
320         firePageAdded( inDestination );
321     }
322
323     public void removePage( Page inPage ) throws RepositoryException
324     {
325         String JavaDoc makeversion = inPage.getProperty("makeversion");
326         if (makeversion != null)
327         {
328             boolean ver = Boolean.parseBoolean(makeversion);
329             inPage.getPageSettings().getXConf().setMakeVersion(ver);
330             inPage.getContentItem().setMakeVersion(ver);
331         }
332         getRepository().remove( inPage.getContentItem() );
333         getRepository().remove( inPage.getPageSettings().getXConf() );
334         getCache().remove( inPage.getPath() );
335         firePageRemoved( inPage );
336     }
337
338     public void putPage( Page inPage ) throws OpenEditException
339     {
340         //Kind of hackish. Guess we need to look on the disk to be sure but that could be slow
341
ContentItem oldItem = inPage.getContentItem();
342         boolean existing = oldItem.exists();
343         try
344         {
345             String JavaDoc makeversion = inPage.getProperty("makeversion");
346             if (makeversion != null)
347             {
348                 boolean ver = Boolean.parseBoolean(makeversion);
349                 oldItem.setMakeVersion(ver);
350             }
351             getRepository().put( oldItem );
352             
353             //we want to get the recent version back from disk
354
if ( oldItem.isMakeVersion() && oldItem.lastModified() == null ) //might be a StringItem for example
355
{
356                 //Load up a fresh item from the disk drive since we uploaded
357
ContentItem reloadedItem = getRepository().get( inPage.getPath() );
358                 if ( oldItem.getMessage() != null && reloadedItem.getMessage() == null )
359                 {
360                     reloadedItem.setAuthor(oldItem.getAuthor());
361                     reloadedItem.setMessage(oldItem.getMessage());
362                     reloadedItem.setType(oldItem.getType());
363                     reloadedItem.setVersion(oldItem.getVersion());
364                 }
365                 reloadedItem.setMakeVersion(oldItem.isMakeVersion());
366                 
367                 inPage.setContentItem( reloadedItem );
368             }
369         }
370         catch (RepositoryException ex)
371         {
372             throw new OpenEditException(ex);
373         }
374         if (existing)
375         {
376             firePageModified( inPage );
377         }
378         else
379         {
380             firePageAdded( inPage );
381         }
382     }
383
384     protected Map JavaDoc getCache()
385     {
386         if (fieldCache == null)
387         {
388             //HARD means even if the object goes out of scope we still keep it in the hashmap
389
//until the memory runs low then things get dumped randomly
390
fieldCache = new ReferenceMap(ReferenceMap.HARD,ReferenceMap.HARD);
391         }
392
393         return fieldCache;
394     }
395
396
397     public Repository getRepository()
398     {
399         return fieldRepository;
400     }
401
402     public void setRepository( Repository repository )
403     {
404         fieldRepository = repository;
405     }
406
407     protected void firePageAdded( Page inPage )
408     {
409         for ( Iterator JavaDoc iter = getPageAccessListeners().keySet().iterator(); iter.hasNext(); )
410         {
411             PageAccessListener listener = (PageAccessListener) iter.next();
412             listener.pageAdded( inPage );
413         }
414     }
415
416     protected void firePageModified( Page page )
417     {
418         for ( Iterator JavaDoc iter = getPageAccessListeners().keySet().iterator(); iter.hasNext(); )
419         {
420             PageAccessListener listener = (PageAccessListener) iter.next();
421             listener.pageModified( page );
422         }
423     }
424
425     protected void firePageRemoved( Page inPage )
426     {
427         for ( Iterator JavaDoc iter = getPageAccessListeners().keySet().iterator(); iter.hasNext(); )
428         {
429             PageAccessListener listener = (PageAccessListener) iter.next();
430             listener.pageRemoved( inPage );
431         }
432     }
433
434     protected void firePageRequested( Page inPage )
435     {
436         for ( Iterator JavaDoc iter = getPageAccessListeners().keySet().iterator(); iter.hasNext(); )
437         {
438             PageAccessListener listener = (PageAccessListener) iter.next();
439             listener.pageRequested( inPage );
440         }
441     }
442
443     protected Map JavaDoc getPageAccessListeners()
444     {
445         if (fieldPageAccessListeners == null)
446         {
447             //HARD means even if the object goes out of scope we still keep it in the hashmap
448
//until the memory runs low then things get dumped randomly
449
fieldPageAccessListeners = new HashMap JavaDoc();
450         }
451
452         return fieldPageAccessListeners;
453     }
454     public void setSettingsManager( PageSettingsManager metaDataConfigurator )
455     {
456         fieldSettingsManager = metaDataConfigurator;
457     }
458     
459     public void addPageAccessListener( PageAccessListener inListener )
460     {
461         getPageAccessListeners().put( inListener, this );
462     }
463     
464     public void removePageAccessListener( PageAccessListener inListener )
465     {
466         getPageAccessListeners().remove( inListener );
467     }
468     public void clearCache()
469     {
470         getCache().clear();
471         getPageSettingsManager().clearCache();
472     }
473
474     /**
475      * @param inPage
476      */

477     public void clearCache(Page inPage)
478     {
479         getCache().remove(inPage.getPath());
480         getPageSettingsManager().clearCache();
481     }
482     public void clearCache(String JavaDoc inPath)
483     {
484         getCache().remove(inPath);
485         getPageSettingsManager().clearCache(inPath);
486     }
487     public void saveContent(Page inXml, User inUser, String JavaDoc inContent, String JavaDoc inMessage) throws OpenEditException
488     {
489         StringItem item = new StringItem(inXml.getPath(),inContent,inXml.getCharacterEncoding());
490         item.setMessage(inMessage);
491         item.setAuthor(inUser.getUserName());
492         inXml.setContentItem(item);
493         putPage(inXml);
494
495     }
496     public List JavaDoc getChildrenNames(String JavaDoc inUrl) throws RepositoryException
497     {
498         return getRepository().getChildrenNames(inUrl);
499     }
500     public ContentItem getLatestVersion(String JavaDoc inPath) throws RepositoryException
501     {
502         return getRepository().getLastVersion(inPath);
503     }
504 }
Popular Tags