Source Code Cross Referenced for VersioningFileProvider.java in  » Wiki-Engine » JSPWiki » com » ecyrd » jspwiki » providers » 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.providers 
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.providers;
021:
022:        import java.io.*;
023:        import java.util.Collection;
024:        import java.util.Iterator;
025:        import java.util.Properties;
026:        import java.util.Date;
027:        import java.util.ArrayList;
028:        import java.util.List;
029:        import org.apache.log4j.Logger;
030:
031:        import com.ecyrd.jspwiki.*;
032:
033:        /**
034:         *  Provides a simple directory based repository for Wiki pages.
035:         *  Pages are held in a directory structure:
036:         *  <PRE>
037:         *    Main.txt
038:         *    Foobar.txt
039:         *    OLD/
040:         *       Main/
041:         *          1.txt
042:         *          2.txt
043:         *          page.properties
044:         *       Foobar/
045:         *          page.properties
046:         *  </PRE>
047:         *
048:         *  In this case, "Main" has three versions, and "Foobar" just one version.
049:         *  <P>
050:         *  The properties file contains the necessary metainformation (such as author)
051:         *  information of the page.  DO NOT MESS WITH IT!
052:         *
053:         *  <P>
054:         *  All files have ".txt" appended to make life easier for those
055:         *  who insist on using Windows or other software which makes assumptions
056:         *  on the files contents based on its name.
057:         *
058:         *  @author Janne Jalkanen
059:         */
060:        public class VersioningFileProvider extends AbstractFileProvider
061:                implements  VersioningProvider {
062:            private static final Logger log = Logger
063:                    .getLogger(VersioningFileProvider.class);
064:
065:            public static final String PAGEDIR = "OLD";
066:            public static final String PROPERTYFILE = "page.properties";
067:
068:            private CachedProperties m_cachedProperties;
069:
070:            public void initialize(WikiEngine engine, Properties properties)
071:                    throws NoRequiredPropertyException, IOException {
072:                super .initialize(engine, properties);
073:            }
074:
075:            /**
076:             *  Returns the directory where the old versions of the pages
077:             *  are being kept.
078:             */
079:            private File findOldPageDir(String page) {
080:                if (page == null) {
081:                    throw new InternalWikiException(
082:                            "Page may NOT be null in the provider!");
083:                }
084:
085:                File oldpages = new File(getPageDirectory(), PAGEDIR);
086:
087:                return new File(oldpages, mangleName(page));
088:            }
089:
090:            /**
091:             *  Goes through the repository and decides which version is
092:             *  the newest one in that directory.
093:             *
094:             *  @return Latest version number in the repository, or -1, if
095:             *          there is no page in the repository.
096:             */
097:
098:            // FIXME: This is relatively slow.
099:            /*
100:            private int findLatestVersion( String page )
101:            {
102:                File pageDir = findOldPageDir( page );
103:
104:                String[] pages = pageDir.list( new WikiFileFilter() );
105:
106:                if( pages == null )
107:                {
108:                    return -1; // No such thing found.
109:                }
110:
111:                int version = -1;
112:
113:                for( int i = 0; i < pages.length; i++ )
114:                {
115:                    int cutpoint = pages[i].indexOf( '.' );
116:                    if( cutpoint > 0 )
117:                    {
118:                        String pageNum = pages[i].substring( 0, cutpoint );
119:
120:                        try
121:                        {
122:                            int res = Integer.parseInt( pageNum );
123:
124:                            if( res > version )
125:                            {
126:                                version = res;
127:                            }
128:                        }
129:                        catch( NumberFormatException e ) {} // It's okay to skip these.
130:                    }
131:                }
132:
133:                return version;
134:            }
135:             */
136:            private int findLatestVersion(String page) throws ProviderException {
137:                int version = -1;
138:
139:                try {
140:                    Properties props = getPageProperties(page);
141:
142:                    for (Iterator i = props.keySet().iterator(); i.hasNext();) {
143:                        String key = (String) i.next();
144:
145:                        if (key.endsWith(".author")) {
146:                            int cutpoint = key.indexOf('.');
147:                            if (cutpoint > 0) {
148:                                String pageNum = key.substring(0, cutpoint);
149:
150:                                try {
151:                                    int res = Integer.parseInt(pageNum);
152:
153:                                    if (res > version) {
154:                                        version = res;
155:                                    }
156:                                } catch (NumberFormatException e) {
157:                                } // It's okay to skip these. 
158:                            }
159:                        }
160:                    }
161:                } catch (IOException e) {
162:                    log.error("Unable to figure out latest version - dying...",
163:                            e);
164:                }
165:
166:                return version;
167:            }
168:
169:            /**
170:             *  Reads page properties from the file system.
171:             */
172:            private Properties getPageProperties(String page)
173:                    throws IOException {
174:                File propertyFile = new File(findOldPageDir(page), PROPERTYFILE);
175:
176:                if (propertyFile.exists()) {
177:                    long lastModified = propertyFile.lastModified();
178:
179:                    //
180:                    //   The profiler showed that when calling the history of a page the propertyfile
181:                    //   was read just as much times as there were versions of that file. The loading
182:                    //   of a propertyfile is a cpu-intensive jobs. So now hold on to the last propertyfile
183:                    //   read because the next method will with a high probability ask for the same propertyfile.
184:                    //   The time it took to show a historypage with 267 versions dropped with 300%. 
185:                    //
186:
187:                    CachedProperties cp = m_cachedProperties;
188:
189:                    if (cp != null && cp.m_page.equals(page)
190:                            && cp.m_lastModified == lastModified) {
191:                        return cp.m_props;
192:                    }
193:
194:                    InputStream in = null;
195:
196:                    try {
197:                        in = new BufferedInputStream(new FileInputStream(
198:                                propertyFile));
199:
200:                        Properties props = new Properties();
201:
202:                        props.load(in);
203:
204:                        cp = new CachedProperties();
205:                        cp.m_page = page;
206:                        cp.m_lastModified = lastModified;
207:                        cp.m_props = props;
208:
209:                        m_cachedProperties = cp; // Atomic
210:
211:                        return props;
212:                    } finally {
213:                        if (in != null)
214:                            in.close();
215:                    }
216:                }
217:
218:                return new Properties(); // Returns an empty object
219:            }
220:
221:            /**
222:             *  Writes the page properties back to the file system.
223:             *  Note that it WILL overwrite any previous properties.
224:             */
225:            private void putPageProperties(String page, Properties properties)
226:                    throws IOException {
227:                File propertyFile = new File(findOldPageDir(page), PROPERTYFILE);
228:                OutputStream out = null;
229:
230:                try {
231:                    out = new FileOutputStream(propertyFile);
232:
233:                    properties.store(out, " JSPWiki page properties for "
234:                            + page + ". DO NOT MODIFY!");
235:                } finally {
236:                    if (out != null)
237:                        out.close();
238:                }
239:            }
240:
241:            /**
242:             *  Figures out the real version number of the page and also checks
243:             *  for its existence.
244:             *
245:             *  @throws NoSuchVersionException if there is no such version.
246:             */
247:            private int realVersion(String page, int requestedVersion)
248:                    throws NoSuchVersionException, ProviderException {
249:                //
250:                //  Quickly check for the most common case.
251:                //
252:                if (requestedVersion == WikiProvider.LATEST_VERSION) {
253:                    return -1;
254:                }
255:
256:                int latest = findLatestVersion(page);
257:
258:                if (requestedVersion == latest
259:                        || (requestedVersion == 1 && latest == -1)) {
260:                    return -1;
261:                } else if (requestedVersion <= 0 || requestedVersion > latest) {
262:                    throw new NoSuchVersionException("Requested version "
263:                            + requestedVersion + ", but latest is " + latest);
264:                }
265:
266:                return requestedVersion;
267:            }
268:
269:            public synchronized String getPageText(String page, int version)
270:                    throws ProviderException {
271:                File dir = findOldPageDir(page);
272:
273:                version = realVersion(page, version);
274:                if (version == -1) {
275:                    // We can let the FileSystemProvider take care
276:                    // of these requests.
277:                    return super .getPageText(page,
278:                            WikiPageProvider.LATEST_VERSION);
279:                }
280:
281:                File pageFile = new File(dir, "" + version + FILE_EXT);
282:
283:                if (!pageFile.exists())
284:                    throw new NoSuchVersionException("Version " + version
285:                            + "does not exist.");
286:
287:                return readFile(pageFile);
288:            }
289:
290:            // FIXME: Should this really be here?
291:            private String readFile(File pagedata) throws ProviderException {
292:                String result = null;
293:                InputStream in = null;
294:
295:                if (pagedata.exists()) {
296:                    if (pagedata.canRead()) {
297:                        try {
298:                            in = new FileInputStream(pagedata);
299:                            result = FileUtil.readContents(in, m_encoding);
300:                        } catch (IOException e) {
301:                            log.error("Failed to read", e);
302:                            throw new ProviderException("I/O error: "
303:                                    + e.getMessage());
304:                        } finally {
305:                            try {
306:                                if (in != null)
307:                                    in.close();
308:                            } catch (Exception e) {
309:                                log.fatal("Closing failed", e);
310:                            }
311:                        }
312:                    } else {
313:                        log.warn("Failed to read page from '"
314:                                + pagedata.getAbsolutePath()
315:                                + "', possibly a permissions problem");
316:                        throw new ProviderException(
317:                                "I cannot read the requested page.");
318:                    }
319:                } else {
320:                    // This is okay.
321:                    // FIXME: is it?
322:                    log.info("New page");
323:                }
324:
325:                return result;
326:            }
327:
328:            // FIXME: This method has no rollback whatsoever.
329:
330:            /*
331:              This is how the page directory should look like:
332:
333:                 version    pagedir       olddir
334:                  none       empty         empty
335:                   1         Main.txt (1)  empty
336:                   2         Main.txt (2)  1.txt
337:                   3         Main.txt (3)  1.txt, 2.txt
338:             */
339:            public synchronized void putPageText(WikiPage page, String text)
340:                    throws ProviderException {
341:                //
342:                //  This is a bit complicated.  We'll first need to
343:                //  copy the old file to be the newest file.
344:                //
345:
346:                File pageDir = findOldPageDir(page.getName());
347:
348:                if (!pageDir.exists()) {
349:                    pageDir.mkdirs();
350:                }
351:
352:                int latest = findLatestVersion(page.getName());
353:
354:                try {
355:                    //
356:                    // Copy old data to safety, if one exists.
357:                    //
358:
359:                    File oldFile = findPage(page.getName());
360:
361:                    // Figure out which version should the old page be?
362:                    // Numbers should always start at 1.
363:                    // "most recent" = -1 ==> 1
364:                    // "first"       = 1  ==> 2
365:
366:                    int versionNumber = (latest > 0) ? latest : 1;
367:
368:                    if (oldFile != null && oldFile.exists()) {
369:                        InputStream in = null;
370:                        OutputStream out = null;
371:
372:                        try {
373:                            in = new BufferedInputStream(new FileInputStream(
374:                                    oldFile));
375:                            File pageFile = new File(pageDir, Integer
376:                                    .toString(versionNumber)
377:                                    + FILE_EXT);
378:                            out = new BufferedOutputStream(
379:                                    new FileOutputStream(pageFile));
380:
381:                            FileUtil.copyContents(in, out);
382:
383:                            //
384:                            // We need also to set the date, since we rely on this.
385:                            //
386:                            pageFile.setLastModified(oldFile.lastModified());
387:
388:                            //
389:                            // Kludge to make the property code to work properly.
390:                            //
391:                            versionNumber++;
392:                        } finally {
393:                            if (out != null)
394:                                out.close();
395:                            if (in != null)
396:                                in.close();
397:                        }
398:                    }
399:
400:                    //
401:                    //  Let superclass handler writing data to a new version.
402:                    //
403:
404:                    super .putPageText(page, text);
405:
406:                    //
407:                    //  Finally, write page version data.
408:                    //
409:
410:                    // FIXME: No rollback available.
411:                    Properties props = getPageProperties(page.getName());
412:
413:                    props.setProperty(versionNumber + ".author", (page
414:                            .getAuthor() != null) ? page.getAuthor()
415:                            : "unknown");
416:
417:                    String changeNote = (String) page
418:                            .getAttribute(WikiPage.CHANGENOTE);
419:                    if (changeNote != null) {
420:                        props.setProperty(versionNumber + ".changenote",
421:                                changeNote);
422:                    }
423:
424:                    putPageProperties(page.getName(), props);
425:                } catch (IOException e) {
426:                    log.error("Saving failed", e);
427:                    throw new ProviderException("Could not save page text: "
428:                            + e.getMessage());
429:                }
430:            }
431:
432:            public WikiPage getPageInfo(String page, int version)
433:                    throws ProviderException {
434:                int latest = findLatestVersion(page);
435:                int realVersion;
436:
437:                WikiPage p = null;
438:
439:                if (version == WikiPageProvider.LATEST_VERSION
440:                        || version == latest || (version == 1 && latest == -1)) {
441:                    //
442:                    // Yes, we need to talk to the top level directory
443:                    // to get this version.
444:                    //
445:                    // I am listening to Press Play On Tape's guitar version of
446:                    // the good old C64 "Wizardry" -tune at this moment.
447:                    // Oh, the memories...
448:                    //
449:                    realVersion = (latest >= 0) ? latest : 1;
450:
451:                    p = super 
452:                            .getPageInfo(page, WikiPageProvider.LATEST_VERSION);
453:
454:                    if (p != null) {
455:                        p.setVersion(realVersion);
456:                    }
457:                } else {
458:                    //
459:                    //  The file is not the most recent, so we'll need to
460:                    //  find it from the deep trenches of the "OLD" directory
461:                    //  structure.
462:                    //
463:                    realVersion = version;
464:                    File dir = findOldPageDir(page);
465:
466:                    if (!dir.exists() || !dir.isDirectory()) {
467:                        return null;
468:                    }
469:
470:                    File file = new File(dir, version + FILE_EXT);
471:
472:                    if (file.exists()) {
473:                        p = new WikiPage(m_engine, page);
474:
475:                        p.setLastModified(new Date(file.lastModified()));
476:                        p.setVersion(version);
477:                    }
478:                }
479:
480:                //
481:                //  Get author and other metadata information
482:                //  (Modification date has already been set.)
483:                //
484:                if (p != null) {
485:                    try {
486:                        Properties props = getPageProperties(page);
487:                        String author = props.getProperty(realVersion
488:                                + ".author");
489:                        if (author != null) {
490:                            p.setAuthor(author);
491:                        }
492:
493:                        String changenote = props.getProperty(realVersion
494:                                + ".changenote");
495:                        if (changenote != null)
496:                            p.setAttribute(WikiPage.CHANGENOTE, changenote);
497:
498:                    } catch (IOException e) {
499:                        log
500:                                .error("Cannot get author for page" + page
501:                                        + ": ", e);
502:                    }
503:                }
504:
505:                return p;
506:            }
507:
508:            public boolean pageExists(String pageName, int version) {
509:                File dir = findOldPageDir(pageName);
510:
511:                if (!dir.exists() || !dir.isDirectory()) {
512:                    return false;
513:                }
514:
515:                File file = new File(dir, version + FILE_EXT);
516:
517:                if (file.exists()) {
518:                    return true;
519:                }
520:
521:                return false;
522:            }
523:
524:            /**
525:             *  FIXME: Does not get user information.
526:             */
527:            public List getVersionHistory(String page) throws ProviderException {
528:                ArrayList list = new ArrayList();
529:
530:                int latest = findLatestVersion(page);
531:
532:                // list.add( getPageInfo(page,WikiPageProvider.LATEST_VERSION) );
533:
534:                for (int i = latest; i > 0; i--) {
535:                    WikiPage info = getPageInfo(page, i);
536:
537:                    if (info != null) {
538:                        list.add(info);
539:                    }
540:                }
541:
542:                return list;
543:            }
544:
545:            /**
546:             *  Removes the relevant page directory under "OLD" -directory as well,
547:             *  but does not remove any extra subdirectories from it.  It will only
548:             *  touch those files that it thinks to be WikiPages.
549:             */
550:            // FIXME: Should log errors.
551:            public void deletePage(String page) throws ProviderException {
552:                super .deletePage(page);
553:
554:                File dir = findOldPageDir(page);
555:
556:                if (dir.exists() && dir.isDirectory()) {
557:                    File[] files = dir.listFiles(new WikiFileFilter());
558:
559:                    for (int i = 0; i < files.length; i++) {
560:                        files[i].delete();
561:                    }
562:
563:                    File propfile = new File(dir, PROPERTYFILE);
564:
565:                    if (propfile.exists()) {
566:                        propfile.delete();
567:                    }
568:
569:                    dir.delete();
570:                }
571:            }
572:
573:            public void deleteVersion(String page, int version)
574:                    throws ProviderException {
575:                File dir = findOldPageDir(page);
576:
577:                int latest = findLatestVersion(page);
578:
579:                if (version == WikiPageProvider.LATEST_VERSION
580:                        || version == latest || (version == 1 && latest == -1)) {
581:                    //
582:                    //  Delete the properties
583:                    //
584:                    try {
585:                        Properties props = getPageProperties(page);
586:                        props.remove(((latest > 0) ? latest : 1) + ".author");
587:                        putPageProperties(page, props);
588:                    } catch (IOException e) {
589:                        log.error("Unable to modify page properties", e);
590:                        throw new ProviderException(
591:                                "Could not modify page properties");
592:                    }
593:
594:                    // We can let the FileSystemProvider take care
595:                    // of the actual deletion
596:                    super .deleteVersion(page, WikiPageProvider.LATEST_VERSION);
597:
598:                    //
599:                    //  Copy the old file to the new location
600:                    //
601:                    latest = findLatestVersion(page);
602:
603:                    File pageDir = findOldPageDir(page);
604:                    File previousFile = new File(pageDir, Integer
605:                            .toString(latest)
606:                            + FILE_EXT);
607:
608:                    InputStream in = null;
609:                    OutputStream out = null;
610:
611:                    try {
612:                        if (previousFile.exists()) {
613:                            in = new BufferedInputStream(new FileInputStream(
614:                                    previousFile));
615:                            File pageFile = findPage(page);
616:                            out = new BufferedOutputStream(
617:                                    new FileOutputStream(pageFile));
618:
619:                            FileUtil.copyContents(in, out);
620:
621:                            //
622:                            // We need also to set the date, since we rely on this.
623:                            //
624:                            pageFile.setLastModified(previousFile
625:                                    .lastModified());
626:                        }
627:                    } catch (IOException e) {
628:                        log
629:                                .fatal(
630:                                        "Something wrong with the page directory - you may have just lost data!",
631:                                        e);
632:                    } finally {
633:                        try {
634:                            if (in != null)
635:                                in.close();
636:                            if (out != null)
637:                                out.close();
638:                        } catch (IOException ex) {
639:                            log.error("Closing failed", ex);
640:                        }
641:                    }
642:
643:                    return;
644:                }
645:
646:                File pageFile = new File(dir, "" + version + FILE_EXT);
647:
648:                if (pageFile.exists()) {
649:                    if (!pageFile.delete()) {
650:                        log.error("Unable to delete page.");
651:                    }
652:                } else {
653:                    throw new NoSuchVersionException("Page " + page
654:                            + ", version=" + version);
655:                }
656:            }
657:
658:            // FIXME: This is kinda slow, we should need to do this only once.
659:            public Collection getAllPages() throws ProviderException {
660:                Collection pages = super .getAllPages();
661:                Collection returnedPages = new ArrayList();
662:
663:                for (Iterator i = pages.iterator(); i.hasNext();) {
664:                    WikiPage page = (WikiPage) i.next();
665:
666:                    WikiPage info = getPageInfo(page.getName(),
667:                            WikiProvider.LATEST_VERSION);
668:
669:                    returnedPages.add(info);
670:                }
671:
672:                return returnedPages;
673:            }
674:
675:            public String getProviderInfo() {
676:                return "";
677:            }
678:
679:            public void movePage(String from, String to)
680:                    throws ProviderException {
681:                // Move the file itself
682:                File fromFile = findPage(from);
683:                File toFile = findPage(to);
684:
685:                fromFile.renameTo(toFile);
686:
687:                // Move any old versions
688:                File fromOldDir = findOldPageDir(from);
689:                File toOldDir = findOldPageDir(to);
690:
691:                fromOldDir.renameTo(toOldDir);
692:            }
693:
694:            private static class CachedProperties {
695:                String m_page;
696:                Properties m_props;
697:                long m_lastModified;
698:            }
699:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.