Source Code Cross Referenced for PageManager.java in  » Wiki-Engine » JSPWiki » com » ecyrd » jspwiki » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Wiki Engine » JSPWiki » com.ecyrd.jspwiki 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:            JSPWiki - a JSP-based WikiWiki clone.
003:
004:            Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
005:
006:            This program is free software; you can redistribute it and/or modify
007:            it under the terms of the GNU Lesser General Public License as published by
008:            the Free Software Foundation; either version 2.1 of the License, or
009:            (at your option) any later version.
010:
011:            This program is distributed in the hope that it will be useful,
012:            but WITHOUT ANY WARRANTY; without even the implied warranty of
013:            MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014:            GNU Lesser General Public License for more details.
015:
016:            You should have received a copy of the GNU Lesser General Public License
017:            along with this program; if not, write to the Free Software
018:            Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
019:         */
020:        package com.ecyrd.jspwiki;
021:
022:        import java.io.IOException;
023:        import java.security.Permission;
024:        import java.security.Principal;
025:        import java.util.*;
026:
027:        import org.apache.commons.lang.ArrayUtils;
028:        import org.apache.log4j.Logger;
029:
030:        import com.ecyrd.jspwiki.auth.WikiPrincipal;
031:        import com.ecyrd.jspwiki.auth.WikiSecurityException;
032:        import com.ecyrd.jspwiki.auth.acl.Acl;
033:        import com.ecyrd.jspwiki.auth.acl.AclEntry;
034:        import com.ecyrd.jspwiki.auth.acl.AclEntryImpl;
035:        import com.ecyrd.jspwiki.auth.user.UserProfile;
036:        import com.ecyrd.jspwiki.event.*;
037:        import com.ecyrd.jspwiki.filters.FilterException;
038:        import com.ecyrd.jspwiki.modules.ModuleManager;
039:        import com.ecyrd.jspwiki.providers.CachingProvider;
040:        import com.ecyrd.jspwiki.providers.ProviderException;
041:        import com.ecyrd.jspwiki.providers.RepositoryModifiedException;
042:        import com.ecyrd.jspwiki.providers.WikiPageProvider;
043:        import com.ecyrd.jspwiki.util.ClassUtil;
044:        import com.ecyrd.jspwiki.util.WikiBackgroundThread;
045:        import com.ecyrd.jspwiki.workflow.Outcome;
046:        import com.ecyrd.jspwiki.workflow.Task;
047:        import com.ecyrd.jspwiki.workflow.Workflow;
048:
049:        /**
050:         *  Manages the WikiPages.  This class functions as an unified interface towards
051:         *  the page providers.  It handles initialization and management of the providers,
052:         *  and provides utility methods for accessing the contents.
053:         *
054:         *  @author Janne Jalkanen
055:         *  @since 2.0
056:         */
057:        // FIXME: This class currently only functions just as an extra layer over providers,
058:        //        complicating things.  We need to move more provider-specific functionality
059:        //        from WikiEngine (which is too big now) into this class.
060:        public class PageManager extends ModuleManager implements 
061:                WikiEventListener {
062:            private static final long serialVersionUID = 1L;
063:
064:            /** The property value for setting the current page provider.  Value is {@value}. */
065:            public static final String PROP_PAGEPROVIDER = "jspwiki.pageProvider";
066:
067:            /** The property value for setting the cache on/off.  Value is {@value}. */
068:            public static final String PROP_USECACHE = "jspwiki.usePageCache";
069:
070:            /** The property value for setting the amount of time before the page locks expire. 
071:             *  Value is {@value}.
072:             */
073:            public static final String PROP_LOCKEXPIRY = "jspwiki.lockExpiryTime";
074:
075:            public static final String PRESAVE_TASK_MESSAGE_KEY = "task.preSaveWikiPage";
076:            public static final String PRESAVE_WIKI_CONTEXT = "wikiContext";
077:            public static final String SAVE_APPROVER = "workflow.saveWikiPage";
078:            public static final String SAVE_DECISION_MESSAGE_KEY = "decision.saveWikiPage";
079:            public static final String SAVE_REJECT_MESSAGE_KEY = "notification.saveWikiPage.reject";
080:            public static final String SAVE_TASK_MESSAGE_KEY = "task.saveWikiPage";
081:
082:            /** Fact name for storing the page name.  Value is {@value}. */
083:            public static final String FACT_PAGE_NAME = "fact.pageName";
084:
085:            /** Fact name for storing a diff text. Value is {@value}. */
086:            public static final String FACT_DIFF_TEXT = "fact.diffText";
087:
088:            /** Fact name for storing the current text.  Value is {@value}. */
089:            public static final String FACT_CURRENT_TEXT = "fact.currentText";
090:
091:            /** Fact name for storing the proposed (edited) text.  Value is {@value}. */
092:            public static final String FACT_PROPOSED_TEXT = "fact.proposedText";
093:
094:            public static final String FACT_IS_AUTHENTICATED = "fact.isAuthenticated";
095:
096:            static Logger log = Logger.getLogger(PageManager.class);
097:
098:            private WikiPageProvider m_provider;
099:
100:            protected HashMap m_pageLocks = new HashMap();
101:
102:            private WikiEngine m_engine;
103:
104:            private int m_expiryTime = 60;
105:
106:            private LockReaper m_reaper = null;
107:
108:            /**
109:             *  Creates a new PageManager.
110:             *  
111:             *  @param engine WikiEngine instance
112:             *  @param props Properties to use for initialization
113:             *  @throws WikiException If anything goes wrong, you get this.
114:             */
115:            public PageManager(WikiEngine engine, Properties props)
116:                    throws WikiException {
117:                super (engine);
118:
119:                String classname;
120:
121:                m_engine = engine;
122:
123:                boolean useCache = "true".equals(props
124:                        .getProperty(PROP_USECACHE));
125:
126:                m_expiryTime = TextUtil.parseIntParameter(props
127:                        .getProperty(PROP_LOCKEXPIRY), 60);
128:
129:                //
130:                //  If user wants to use a cache, then we'll use the CachingProvider.
131:                //
132:                if (useCache) {
133:                    classname = "com.ecyrd.jspwiki.providers.CachingProvider";
134:                } else {
135:                    classname = WikiEngine.getRequiredProperty(props,
136:                            PROP_PAGEPROVIDER);
137:                }
138:
139:                try {
140:                    log.debug("Page provider class: '" + classname + "'");
141:
142:                    Class providerclass = ClassUtil.findClass(
143:                            "com.ecyrd.jspwiki.providers", classname);
144:
145:                    m_provider = (WikiPageProvider) providerclass.newInstance();
146:
147:                    log.debug("Initializing page provider class " + m_provider);
148:                    m_provider.initialize(m_engine, props);
149:                } catch (ClassNotFoundException e) {
150:                    log.error("Unable to locate provider class '" + classname
151:                            + "'", e);
152:                    throw new WikiException("no provider class");
153:                } catch (InstantiationException e) {
154:                    log.error("Unable to create provider class '" + classname
155:                            + "'", e);
156:                    throw new WikiException("faulty provider class");
157:                } catch (IllegalAccessException e) {
158:                    log.error("Illegal access to provider class '" + classname
159:                            + "'", e);
160:                    throw new WikiException("illegal provider class");
161:                } catch (NoRequiredPropertyException e) {
162:                    log.error(
163:                            "Provider did not found a property it was looking for: "
164:                                    + e.getMessage(), e);
165:                    throw e; // Same exception works.
166:                } catch (IOException e) {
167:                    log.error(
168:                            "An I/O exception occurred while trying to create a new page provider: "
169:                                    + classname, e);
170:                    throw new WikiException("Unable to start page provider: "
171:                            + e.getMessage());
172:                }
173:
174:            }
175:
176:            /**
177:             *  Returns the page provider currently in use.
178:             *  
179:             *  @return A WikiPageProvider instance.
180:             */
181:            public WikiPageProvider getProvider() {
182:                return m_provider;
183:            }
184:
185:            /**
186:             *  Returns all pages in some random order.  If you need just the page names, 
187:             *  please see {@link ReferenceManager#findCreated()}, which is probably a lot
188:             *  faster.  This method may cause repository access.
189:             *  
190:             *  @return A Collection of WikiPage objects.
191:             *  @throws ProviderException If the backend has problems.
192:             */
193:            public Collection getAllPages() throws ProviderException {
194:                return m_provider.getAllPages();
195:            }
196:
197:            /**
198:             *  Fetches the page text from the repository.  This method also does some sanity checks,
199:             *  like checking for the pageName validity, etc.  Also, if the page repository has been
200:             *  modified externally, it is smart enough to handle such occurrences.
201:             *  
202:             *  @param pageName The name of the page to fetch.
203:             *  @param version The version to find
204:             *  @return The page content as a raw string
205:             *  @throws ProviderException If the backend has issues.
206:             */
207:            public String getPageText(String pageName, int version)
208:                    throws ProviderException {
209:                if (pageName == null || pageName.length() == 0) {
210:                    throw new ProviderException("Illegal page name");
211:                }
212:
213:                String text = null;
214:
215:                try {
216:                    text = m_provider.getPageText(pageName, version);
217:                } catch (RepositoryModifiedException e) {
218:                    //
219:                    //  This only occurs with the latest version.
220:                    //
221:                    log
222:                            .info("Repository has been modified externally while fetching page "
223:                                    + pageName);
224:
225:                    //
226:                    //  Empty the references and yay, it shall be recalculated
227:                    //
228:                    //WikiPage p = new WikiPage( pageName );
229:                    WikiPage p = m_provider.getPageInfo(pageName, version);
230:
231:                    m_engine.updateReferences(p);
232:
233:                    if (p != null) {
234:                        m_engine.getSearchManager().reindexPage(p);
235:                        text = m_provider.getPageText(pageName, version);
236:                    } else {
237:                        //
238:                        //  Make sure that it no longer exists in internal data structures either.
239:                        //
240:                        WikiPage dummy = new WikiPage(m_engine, pageName);
241:                        m_engine.getSearchManager().pageRemoved(dummy);
242:                        m_engine.getReferenceManager().pageRemoved(dummy);
243:                    }
244:                }
245:
246:                return text;
247:            }
248:
249:            /**
250:             *  Returns the WikiEngine to which this PageManager belongs to.
251:             *  
252:             *  @return The WikiEngine object.
253:             */
254:            public WikiEngine getEngine() {
255:                return m_engine;
256:            }
257:
258:            /**
259:             *  Puts the page text into the repository.  Note that this method does NOT update
260:             *  JSPWiki internal data structures, and therefore you should always use WikiEngine.saveText()
261:             *
262:             * @param page Page to save
263:             * @param content Wikimarkup to save
264:             * @throws ProviderException If something goes wrong in the saving phase
265:             */
266:            public void putPageText(WikiPage page, String content)
267:                    throws ProviderException {
268:                if (page == null || page.getName() == null
269:                        || page.getName().length() == 0) {
270:                    throw new ProviderException("Illegal page name");
271:                }
272:
273:                m_provider.putPageText(page, content);
274:            }
275:
276:            /**
277:             *  Locks page for editing.  Note, however, that the PageManager
278:             *  will in no way prevent you from actually editing this page;
279:             *  the lock is just for information.
280:             *
281:             *  @param page WikiPage to lock
282:             *  @param user Username to use for locking
283:             *  @return null, if page could not be locked.
284:             */
285:            public PageLock lockPage(WikiPage page, String user) {
286:                PageLock lock = null;
287:
288:                if (m_reaper == null) {
289:                    //
290:                    //  Start the lock reaper lazily.  We don't want to start it in
291:                    //  the constructor, because starting threads in constructors
292:                    //  is a bad idea when it comes to inheritance.  Besides,
293:                    //  laziness is a virtue.
294:                    //
295:                    m_reaper = new LockReaper(m_engine);
296:                    m_reaper.start();
297:                }
298:
299:                synchronized (m_pageLocks) {
300:                    fireEvent(WikiPageEvent.PAGE_LOCK, page.getName()); // prior to or after actual lock?
301:
302:                    lock = (PageLock) m_pageLocks.get(page.getName());
303:
304:                    if (lock == null) {
305:                        //
306:                        //  Lock is available, so make a lock.
307:                        //
308:                        Date d = new Date();
309:                        lock = new PageLock(page, user, d, new Date(d.getTime()
310:                                + m_expiryTime * 60 * 1000L));
311:
312:                        m_pageLocks.put(page.getName(), lock);
313:
314:                        log.debug("Locked page " + page.getName() + " for "
315:                                + user);
316:                    } else {
317:                        log.debug("Page " + page.getName()
318:                                + " already locked by " + lock.getLocker());
319:                        lock = null; // Nothing to return
320:                    }
321:                }
322:
323:                return lock;
324:            }
325:
326:            /**
327:             *  Marks a page free to be written again.  If there has not been a lock,
328:             *  will fail quietly.
329:             *
330:             *  @param lock A lock acquired in lockPage().  Safe to be null.
331:             */
332:            public void unlockPage(PageLock lock) {
333:                if (lock == null)
334:                    return;
335:
336:                synchronized (m_pageLocks) {
337:                    m_pageLocks.remove(lock.getPage());
338:
339:                    log.debug("Unlocked page " + lock.getPage());
340:                }
341:
342:                fireEvent(WikiPageEvent.PAGE_UNLOCK, lock.getPage());
343:            }
344:
345:            /**
346:             *  Returns the current lock owner of a page.  If the page is not
347:             *  locked, will return null.
348:             *
349:             *  @param page The page to check the lock for
350:             *  @return Current lock, or null, if there is no lock
351:             */
352:            public PageLock getCurrentLock(WikiPage page) {
353:                PageLock lock = null;
354:
355:                synchronized (m_pageLocks) {
356:                    lock = (PageLock) m_pageLocks.get(page.getName());
357:                }
358:
359:                return lock;
360:            }
361:
362:            /**
363:             *  Returns a list of currently applicable locks.  Note that by the time you get the list,
364:             *  the locks may have already expired, so use this only for informational purposes.
365:             *
366:             *  @return List of PageLock objects, detailing the locks.  If no locks exist, returns
367:             *          an empty list.
368:             *  @since 2.0.22.
369:             */
370:            public List getActiveLocks() {
371:                ArrayList result = new ArrayList();
372:
373:                synchronized (m_pageLocks) {
374:                    for (Iterator i = m_pageLocks.values().iterator(); i
375:                            .hasNext();) {
376:                        result.add(i.next());
377:                    }
378:                }
379:
380:                return result;
381:            }
382:
383:            /**
384:             *  Finds a WikiPage object describing a particular page and version.
385:             *  
386:             *  @param pageName  The name of the page
387:             *  @param version   A version number
388:             *  @return          A WikiPage object, or null, if the page does not exist
389:             *  @throws ProviderException If there is something wrong with the page 
390:             *                            name or the repository
391:             */
392:            public WikiPage getPageInfo(String pageName, int version)
393:                    throws ProviderException {
394:                if (pageName == null || pageName.length() == 0) {
395:                    throw new ProviderException("Illegal page name '"
396:                            + pageName + "'");
397:                }
398:
399:                WikiPage page = null;
400:
401:                try {
402:                    page = m_provider.getPageInfo(pageName, version);
403:                } catch (RepositoryModifiedException e) {
404:                    //
405:                    //  This only occurs with the latest version.
406:                    //
407:                    log
408:                            .info("Repository has been modified externally while fetching info for "
409:                                    + pageName);
410:
411:                    WikiPage p = new WikiPage(m_engine, pageName);
412:
413:                    m_engine.updateReferences(p);
414:
415:                    page = m_provider.getPageInfo(pageName, version);
416:                }
417:
418:                //
419:                //  Should update the metadata.
420:                //
421:                /*
422:                if( page != null && !page.hasMetadata() )
423:                {
424:                    WikiContext ctx = new WikiContext(m_engine,page);
425:                    m_engine.textToHTML( ctx, getPageText(pageName,version) );
426:                }
427:                 */
428:                return page;
429:            }
430:
431:            /**
432:             *  Gets a version history of page.  Each element in the returned
433:             *  List is a WikiPage.
434:             *  
435:             *  @param pageName The name of the page to fetch history for
436:             *  @return If the page does not exist, returns null, otherwise a List
437:             *          of WikiPages.
438:             *  @throws ProviderException If the repository fails.
439:             */
440:            public List getVersionHistory(String pageName)
441:                    throws ProviderException {
442:                if (pageExists(pageName)) {
443:                    return m_provider.getVersionHistory(pageName);
444:                }
445:
446:                return null;
447:            }
448:
449:            /**
450:             *  Returns a human-readable description of the current provider.
451:             *  
452:             *  @return A human-readable description.
453:             */
454:            public String getProviderDescription() {
455:                return m_provider.getProviderInfo();
456:            }
457:
458:            /**
459:             *  Returns the total count of all pages in the repository. This
460:             *  method is equivalent of calling getAllPages().size(), but
461:             *  it swallows the ProviderException and returns -1 instead of
462:             *  any problems.
463:             *  
464:             *  @return The number of pages, or -1, if there is an error.
465:             */
466:            public int getTotalPageCount() {
467:                try {
468:                    return m_provider.getAllPages().size();
469:                } catch (ProviderException e) {
470:                    log.error("Unable to count pages: ", e);
471:                    return -1;
472:                }
473:            }
474:
475:            /**
476:             *  Returns true, if the page exists (any version).
477:             *  
478:             *  @param pageName  Name of the page.
479:             *  @return A boolean value describing the existence of a page
480:             *  @throws ProviderException If the backend fails or the name is illegal.
481:             */
482:            public boolean pageExists(String pageName) throws ProviderException {
483:                if (pageName == null || pageName.length() == 0) {
484:                    throw new ProviderException("Illegal page name");
485:                }
486:
487:                return m_provider.pageExists(pageName);
488:            }
489:
490:            /**
491:             *  Checks for existence of a specific page and version.
492:             *  
493:             *  @since 2.3.29
494:             *  @param pageName Name of the page
495:             *  @param version The version to check
496:             *  @return <code>true</code> if the page exists, <code>false</code> otherwise
497:             *  @throws ProviderException If backend fails or name is illegal
498:             */
499:            public boolean pageExists(String pageName, int version)
500:                    throws ProviderException {
501:                if (pageName == null || pageName.length() == 0) {
502:                    throw new ProviderException("Illegal page name");
503:                }
504:
505:                if (version == WikiProvider.LATEST_VERSION)
506:                    return pageExists(pageName);
507:
508:                if (m_provider instanceof  CachingProvider) {
509:                    return ((CachingProvider) m_provider).pageExists(pageName,
510:                            version);
511:                }
512:
513:                return m_provider.getPageInfo(pageName, version) != null;
514:            }
515:
516:            /**
517:             *  Deletes only a specific version of a WikiPage.
518:             *  
519:             *  @param page The page to delete.
520:             *  @throws ProviderException if the page fails
521:             */
522:            public void deleteVersion(WikiPage page) throws ProviderException {
523:                m_provider.deleteVersion(page.getName(), page.getVersion());
524:
525:                // FIXME: If this was the latest, reindex Lucene
526:                // FIXME: Update RefMgr
527:            }
528:
529:            /**
530:             *  Deletes an entire page, all versions, all traces.
531:             *  
532:             *  @param page The WikiPage to delete
533:             *  @throws ProviderException If the repository operation fails
534:             */
535:            public void deletePage(WikiPage page) throws ProviderException {
536:                fireEvent(WikiPageEvent.PAGE_DELETE_REQUEST, page.getName());
537:
538:                m_provider.deletePage(page.getName());
539:
540:                fireEvent(WikiPageEvent.PAGE_DELETED, page.getName());
541:            }
542:
543:            /**
544:             *  This is a simple reaper thread that runs roughly every minute
545:             *  or so (it's not really that important, as long as it runs),
546:             *  and removes all locks that have expired.
547:             */
548:            private class LockReaper extends WikiBackgroundThread {
549:                public LockReaper(WikiEngine engine) {
550:                    super (engine, 60);
551:                    setName("JSPWiki Lock Reaper");
552:                }
553:
554:                public void backgroundTask() throws Exception {
555:                    synchronized (m_pageLocks) {
556:                        Collection entries = m_pageLocks.values();
557:
558:                        Date now = new Date();
559:
560:                        for (Iterator i = entries.iterator(); i.hasNext();) {
561:                            PageLock p = (PageLock) i.next();
562:
563:                            if (now.after(p.getExpiryTime())) {
564:                                i.remove();
565:
566:                                log.debug("Reaped lock: " + p.getPage()
567:                                        + " by " + p.getLocker()
568:                                        + ", acquired "
569:                                        + p.getAcquisitionTime()
570:                                        + ", and expired " + p.getExpiryTime());
571:                            }
572:                        }
573:                    }
574:                }
575:            }
576:
577:            // workflow task inner classes....................................................
578:
579:            /**
580:             * Inner class that handles the page pre-save actions. If the proposed page
581:             * text is the same as the current version, the {@link #execute()} method
582:             * returns {@link com.ecyrd.jspwiki.workflow.Outcome#STEP_ABORT}. Any
583:             * WikiExceptions thrown by page filters will be re-thrown, and the workflow
584:             * will abort.
585:             *
586:             * @author Andrew Jaquith
587:             */
588:            public static class PreSaveWikiPageTask extends Task {
589:                private final WikiContext m_context;
590:                private final String m_proposedText;
591:
592:                public PreSaveWikiPageTask(WikiContext context,
593:                        String proposedText) {
594:                    super (PRESAVE_TASK_MESSAGE_KEY);
595:                    m_context = context;
596:                    m_proposedText = proposedText;
597:                }
598:
599:                public Outcome execute() throws WikiException {
600:                    // Retrieve attributes
601:                    WikiEngine engine = m_context.getEngine();
602:                    Workflow workflow = getWorkflow();
603:
604:                    // Get the wiki page
605:                    WikiPage page = m_context.getPage();
606:
607:                    // Figure out who the author was. Prefer the author
608:                    // set programmatically; otherwise get from the
609:                    // current logged in user
610:                    if (page.getAuthor() == null) {
611:                        Principal wup = m_context.getCurrentUser();
612:
613:                        if (wup != null)
614:                            page.setAuthor(wup.getName());
615:                    }
616:
617:                    // Run the pre-save filters. If any exceptions, add error to list, abort, and redirect
618:                    String saveText;
619:                    try {
620:                        saveText = engine.getFilterManager()
621:                                .doPreSaveFiltering(m_context, m_proposedText);
622:                    } catch (FilterException e) {
623:                        throw e;
624:                    }
625:
626:                    // Stash the wiki context, old and new text as workflow attributes
627:                    workflow.setAttribute(PRESAVE_WIKI_CONTEXT, m_context);
628:                    workflow.setAttribute(FACT_PROPOSED_TEXT, saveText);
629:                    return Outcome.STEP_COMPLETE;
630:                }
631:            }
632:
633:            /**
634:             * Inner class that handles the actual page save and post-save actions. Instances
635:             * of this class are assumed to have been added to an approval workflow via
636:             * {@link com.ecyrd.jspwiki.workflow.WorkflowBuilder#buildApprovalWorkflow(Principal, String, Task, String, com.ecyrd.jspwiki.workflow.Fact[], Task, String)};
637:             * they will not function correctly otherwise.
638:             *
639:             * @author Andrew Jaquith
640:             */
641:            public static class SaveWikiPageTask extends Task {
642:                public SaveWikiPageTask() {
643:                    super (SAVE_TASK_MESSAGE_KEY);
644:                }
645:
646:                public Outcome execute() throws WikiException {
647:                    // Retrieve attributes
648:                    WikiContext context = (WikiContext) getWorkflow()
649:                            .getAttribute(PRESAVE_WIKI_CONTEXT);
650:                    String proposedText = (String) getWorkflow().getAttribute(
651:                            FACT_PROPOSED_TEXT);
652:
653:                    WikiEngine engine = context.getEngine();
654:                    WikiPage page = context.getPage();
655:
656:                    // Let the rest of the engine handle actual saving.
657:                    engine.getPageManager().putPageText(page, proposedText);
658:
659:                    // Refresh the context for post save filtering.
660:                    engine.getPage(page.getName());
661:                    engine.textToHTML(context, proposedText);
662:                    engine.getFilterManager().doPostSaveFiltering(context,
663:                            proposedText);
664:
665:                    return Outcome.STEP_COMPLETE;
666:                }
667:            }
668:
669:            // events processing .......................................................
670:
671:            /**
672:             *  Fires a WikiPageEvent of the provided type and page name
673:             *  to all registered listeners.
674:             *
675:             * @see com.ecyrd.jspwiki.event.WikiPageEvent
676:             * @param type       the event type to be fired
677:             * @param pagename   the wiki page name as a String
678:             */
679:            protected final void fireEvent(int type, String pagename) {
680:                if (WikiEventManager.isListening(this )) {
681:                    WikiEventManager.fireEvent(this , new WikiPageEvent(
682:                            m_engine, type, pagename));
683:                }
684:            }
685:
686:            /**
687:             *  {@inheritDoc}
688:             */
689:            public Collection modules() {
690:                // TODO Auto-generated method stub
691:                return null;
692:            }
693:
694:            /**
695:             *  Listens for {@link com.ecyrd.jspwiki.event.WikiSecurityEvent#PROFILE_NAME_CHANGED}
696:             *  events. If a user profile's name changes, each page ACL is inspected. If an entry contains
697:             *  a name that has changed, it is replaced with the new one. No events are emitted
698:             *  as a consequence of this method, because the page contents are still the same; it is
699:             *  only the representations of the names within the ACL that are changing.
700:             * 
701:             *  @param event The event
702:             */
703:            public void actionPerformed(WikiEvent event) {
704:                if (!(event instanceof  WikiSecurityEvent)) {
705:                    return;
706:                }
707:
708:                WikiSecurityEvent se = (WikiSecurityEvent) event;
709:                if (se.getType() == WikiSecurityEvent.PROFILE_NAME_CHANGED) {
710:                    UserProfile[] profiles = (UserProfile[]) se.getTarget();
711:                    Principal[] oldPrincipals = new Principal[] {
712:                            new WikiPrincipal(profiles[0].getLoginName()),
713:                            new WikiPrincipal(profiles[0].getFullname()),
714:                            new WikiPrincipal(profiles[0].getWikiName()) };
715:                    Principal newPrincipal = new WikiPrincipal(profiles[1]
716:                            .getFullname());
717:
718:                    // Examine each page ACL
719:                    try {
720:                        int pagesChanged = 0;
721:                        Collection pages = getAllPages();
722:                        for (Iterator it = pages.iterator(); it.hasNext();) {
723:                            WikiPage page = (WikiPage) it.next();
724:                            boolean aclChanged = changeAcl(page, oldPrincipals,
725:                                    newPrincipal);
726:                            if (aclChanged) {
727:                                // If the Acl needed changing, change it now
728:                                try {
729:                                    m_engine.getAclManager().setPermissions(
730:                                            page, page.getAcl());
731:                                } catch (WikiSecurityException e) {
732:                                    log
733:                                            .error("Could not change page ACL for page "
734:                                                    + page.getName()
735:                                                    + ": "
736:                                                    + e.getMessage());
737:                                }
738:                                pagesChanged++;
739:                            }
740:                        }
741:                        log.info("Profile name change for '"
742:                                + newPrincipal.toString() + "' caused "
743:                                + pagesChanged + " page ACLs to change also.");
744:                    } catch (ProviderException e) {
745:                        // Oooo! This is really bad...
746:                        log
747:                                .error("Could not change user name in Page ACLs because of Provider error:"
748:                                        + e.getMessage());
749:                    }
750:                }
751:            }
752:
753:            /**
754:             *  For a single wiki page, replaces all Acl entries matching a supplied array of Principals 
755:             *  with a new Principal.
756:             * 
757:             *  @param page the wiki page whose Acl is to be modified
758:             *  @param oldPrincipals an array of Principals to replace; all AclEntry objects whose
759:             *   {@link AclEntry#getPrincipal()} method returns one of these Principals will be replaced
760:             *  @param newPrincipal the Principal that should receive the old Principals' permissions
761:             *  @return <code>true</code> if the Acl was actually changed; <code>false</code> otherwise
762:             */
763:            protected boolean changeAcl(WikiPage page,
764:                    Principal[] oldPrincipals, Principal newPrincipal) {
765:                Acl acl = page.getAcl();
766:                boolean pageChanged = false;
767:                if (acl != null) {
768:                    Enumeration entries = acl.entries();
769:                    Collection entriesToAdd = new ArrayList();
770:                    Collection entriesToRemove = new ArrayList();
771:                    while (entries.hasMoreElements()) {
772:                        AclEntry entry = (AclEntry) entries.nextElement();
773:                        if (ArrayUtils.contains(oldPrincipals, entry
774:                                .getPrincipal())) {
775:                            // Create new entry
776:                            AclEntry newEntry = new AclEntryImpl();
777:                            newEntry.setPrincipal(newPrincipal);
778:                            Enumeration permissions = entry.permissions();
779:                            while (permissions.hasMoreElements()) {
780:                                Permission permission = (Permission) permissions
781:                                        .nextElement();
782:                                newEntry.addPermission(permission);
783:                            }
784:                            pageChanged = true;
785:                            entriesToRemove.add(entry);
786:                            entriesToAdd.add(newEntry);
787:                        }
788:                    }
789:                    for (Iterator ix = entriesToRemove.iterator(); ix.hasNext();) {
790:                        AclEntry entry = (AclEntry) ix.next();
791:                        acl.removeEntry(entry);
792:                    }
793:                    for (Iterator ix = entriesToAdd.iterator(); ix.hasNext();) {
794:                        AclEntry entry = (AclEntry) ix.next();
795:                        acl.addEntry(entry);
796:                    }
797:                }
798:                return pageChanged;
799:            }
800:
801:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.