File Source: staticpageindex.java

     1  /*
     2   * Copyright (c) 2003-2006, Simon Brown
     3   * All rights reserved.
     4   *
     5   * Redistribution and use in source and binary forms, with or without
     6   * modification, are permitted provided that the following conditions are met:
     7   *
     8   *   - Redistributions of source code must retain the above copyright
     9   *     notice, this list of conditions and the following disclaimer.
    10   *
    11   *   - Redistributions in binary form must reproduce the above copyright
    12   *     notice, this list of conditions and the following disclaimer in
    13   *     the documentation and/or other materials provided with the
    14   *     distribution.
    15   *
    16   *   - Neither the name of Pebble nor the names of its contributors may
    17   *     be used to endorse or promote products derived from this software
    18   *     without specific prior written permission.
    19   *
    20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
    24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    30   * POSSIBILITY OF SUCH DAMAGE.
    31   */
    32  package net.sourceforge.pebble.index;
    33  
    34  import net.sourceforge.pebble.domain.Blog;
    35  import net.sourceforge.pebble.domain.StaticPage;
    36  import org.apache.commons.logging.Log;
    37  import org.apache.commons.logging.LogFactory;
    38  
    39  import java.io.*;
    40  import java.util.*;
    41  
    42  /**
    43   * Maintains an index of all static pages
    44   *
    45   * @author    Simon Brown
    46   */
    47  public class StaticPageIndex {
    48  
           /* 
    P/P     *  Method: net.sourceforge.pebble.index.StaticPageIndex__static_init
            * 
            *  Postconditions:
            *    init'ed(log)
            */
    49    private static final Log log = LogFactory.getLog(StaticPageIndex.class);
    50  
    51    private static final String PAGES_INDEX_DIRECTORY_NAME = "pages";
    52    private static final String NAME_TO_ID_INDEX_FILE_NAME = "name.index";
    53    private static final String LOCK_FILE_NAME = "pages.lock";
    54    private static final int MAXIMUM_LOCK_ATTEMPTS = 3;
    55  
    56    /** the owning blog */
    57    private Blog blog;
    58  
    59    /** the collection of all static pages */
    60    private Map<String,String> index = new HashMap<String,String>();
    61    private int lockAttempts = 0;
    62  
           /* 
    P/P     *  Method: void net.sourceforge.pebble.index.StaticPageIndex(Blog)
            * 
            *  Preconditions:
            *    blog != null
            * 
            *  Postconditions:
            *    this.blog == blog
            *    this.blog != null
            *    this.index == &new HashMap(StaticPageIndex#1)
            *    init'ed(this.lockAttempts)
            *    new HashMap(StaticPageIndex#1) num objects == 1
            * 
            *  Test Vectors:
            *    java.io.File:exists(...)@68: {1}, {0}
            */
    63    public StaticPageIndex(Blog blog) {
    64      this.blog = blog;
    65  
    66      // create the directory structure if it doesn't exist
    67      File indexDirectory = new File(blog.getIndexesDirectory(), PAGES_INDEX_DIRECTORY_NAME);
    68      if (!indexDirectory.exists()) {
    69        indexDirectory.mkdirs();
    70      }
    71  
    72      readIndex();
    73    }
    74  
    75    /**
    76     * Indexes one or more blog entries.
    77     *
    78     * @param staticPages   a List of Page instances
    79     */
    80    public synchronized void reindex(Collection<StaticPage> staticPages) {
             /* 
    P/P       *  Method: void reindex(Collection)
              * 
              *  Preconditions:
              *    this.blog != null
              *    (soft) this.lockAttempts <= 232-2
              *    (soft) staticPages != null
              * 
              *  Presumptions:
              *    java.util.Iterator:next(...)@84 != null
              * 
              *  Postconditions:
              *    this.index == One-of{old this.index, &new HashMap(reindex#1)}
              *    this.lockAttempts == One-of{old this.lockAttempts, old this.lockAttempts + 1, 0}
              *    init'ed(this.lockAttempts)
              *    new HashMap(reindex#1) num objects <= 1
              * 
              *  Test Vectors:
              *    java.util.Iterator:hasNext(...)@84: {1}, {0}
              */
    81      if (lock()) {
    82        // clear the index and add all static pages
    83        index = new HashMap<String,String>();
    84        for (StaticPage staticPage : staticPages) {
    85          index.put(staticPage.getName(), staticPage.getId());
    86        }
    87  
    88        // and finally, write the index
    89        writeIndex();
    90        unlock();
    91      }
    92    }
    93  
    94    /**
    95     * Indexes a single page.
    96     *
    97     * @param staticPage    a Page instance
    98     */
    99    public synchronized void index(StaticPage staticPage) {
             /* 
    P/P       *  Method: void index(StaticPage)
              * 
              *  Preconditions:
              *    this.blog != null
              *    (soft) this.lockAttempts <= 232-2
              *    (soft) staticPage != null
              *    (soft) init'ed(staticPage.name)
              *    (soft) this.index != null
              * 
              *  Presumptions:
              *    java.util.Map:get(...)@107 != null
              *    java.util.Map:keySet(...)@104 != null
              * 
              *  Postconditions:
              *    init'ed(this.lockAttempts)
              * 
              *  Test Vectors:
              *    java.lang.String:equals(...)@108: {0}, {1}
              *    java.util.Iterator:hasNext(...)@105: {1}, {0}
              */
   100      if (lock()) {
   101        readIndex();
   102  
   103        // remove the old entry for this static page
   104        Iterator it = index.keySet().iterator();
   105        while (it.hasNext()) {
   106          String key = (String)it.next();
   107          String value = index.get(key);
   108          if (value.equals(staticPage.getId())) {
   109            it.remove();
   110          }
   111        }
   112  
   113        // and now add the new entry for this page
   114        index.put(staticPage.getName(), staticPage.getId());
   115        writeIndex();
   116        unlock();
   117      } else {
   118        if (lockAttempts <= MAXIMUM_LOCK_ATTEMPTS) {
   119          try {
   120            Thread.sleep(1000);
   121          } catch (InterruptedException ie) {
   122            // ignore
   123          }
   124          index(staticPage);
   125        } else {
   126          blog.error("Could not index static page - try <a href=\"utilities.secureaction?action=buildIndexes\">rebuilding the indexes</a>.");
   127        }
   128      }
   129    }
   130  
   131    /**
   132     * Unindexes a single page.
   133     *
   134     * @param staticPage    a Page instance
   135     */
   136    public synchronized void unindex(StaticPage staticPage) {
             /* 
    P/P       *  Method: void unindex(StaticPage)
              * 
              *  Preconditions:
              *    this.blog != null
              *    (soft) this.lockAttempts <= 232-2
              *    (soft) staticPage != null
              *    (soft) init'ed(staticPage.name)
              *    (soft) this.index != null
              * 
              *  Postconditions:
              *    init'ed(this.lockAttempts)
              * 
              *  Preconditions:
              *    (soft) net/sourceforge/pebble/dao/DAOFactory.configuredFactory != null
              *    (soft) net/sourceforge/pebble/dao/DAOFactory.configuredFactory.staticPageDAO != null
              *    (soft) net/sourceforge/pebble/domain/AbstractBlog.log != null
              *    (soft) net/sourceforge/pebble/domain/BlogManager.instance != null
              *    (soft) init'ed(net/sourceforge/pebble/domain/BlogManager.instance.multiBlog)
              *    (soft) this...lockAttempts <= 232-2
              *    (soft) this.blog.messages != null
              *    (soft) this...blog != null
              *    (soft) this.blog...properties != null
              *    (soft) this.blog.searchIndex != null
              *    ...
              * 
              *  Presumptions:
              *    net/sourceforge/pebble/dao/DAOFactory.configuredFactory.staticPageDAO@145 != null
              *    net/sourceforge/pebble/dao/DAOFactory.configuredFactory@145 != null
              *    net/sourceforge/pebble/domain/AbstractBlog.log@145 != null
              *    net/sourceforge/pebble/domain/BlogManager.instance@145 != null
              * 
              *  Postconditions:
              *    possibly_updated(this...index)
              *    (soft) init'ed(this...lockAttempts)
              *    init'ed(this.blog.messages)
              *    new HashMap(reindex#1) num objects <= 1
              */
   137      if (lock()) {
   138        readIndex();
   139        index.remove(staticPage.getName());
   140        writeIndex();
   141        unlock();
   142      } else {
   143        if (lockAttempts <= MAXIMUM_LOCK_ATTEMPTS) {
   144          try {
   145            Thread.sleep(1000);
   146          } catch (InterruptedException ie) {
   147            // ignore
   148          }
   149          unindex(staticPage);
   150        } else {
   151          blog.reindexStaticPages();
   152        }
   153      }
   154    }
   155  
   156    /**
   157     * Helper method to load the index.
   158     */
   159    private void readIndex() {
             /* 
    P/P       *  Method: void readIndex()
              * 
              *  Preconditions:
              *    this.blog != null
              *    (soft) this.index != null
              * 
              *  Presumptions:
              *    org.apache.commons.logging.LogFactory:getLog(...)@49 != null
              *    parts.length@167 >= 2
              * 
              *  Test Vectors:
              *    java.io.File:exists(...)@162: {0}, {1}
              */
   160      log.info("Reading index from disk");
   161      File indexFile = getIndexFile();
   162      if (indexFile.exists()) {
   163        try {
   164          BufferedReader reader = new BufferedReader(new FileReader(indexFile));
   165          String indexEntry = reader.readLine();
   166          while (indexEntry != null) {
   167            String[] parts = indexEntry.split("=");
   168            index.put(parts[0], parts[1]);
   169  
   170            indexEntry = reader.readLine();
   171          }
   172  
   173          reader.close();
   174        } catch (Exception e) {
   175          log.error("Error while reading index", e);
   176        }
   177      }
   178    }
   179  
   180    /**
   181     * Helper method to write out the index to disk.
   182     */
   183    private void writeIndex() {
   184      try {
               /* 
    P/P         *  Method: void writeIndex()
                * 
                *  Preconditions:
                *    (soft) this.blog != null
                *    (soft) this.index != null
                * 
                *  Presumptions:
                *    java.util.Map:keySet(...)@188 != null
                *    org.apache.commons.logging.LogFactory:getLog(...)@49 != null
                * 
                *  Test Vectors:
                *    java.util.Iterator:hasNext(...)@188: {1}, {0}
                */
   185        File indexFile = getIndexFile();
   186        BufferedWriter writer = new BufferedWriter(new FileWriter(indexFile));
   187  
   188        for (String name : index.keySet()) {
   189          writer.write(name + "=" + index.get(name));
   190          writer.newLine();
   191        }
   192  
   193        writer.flush();
   194        writer.close();
   195      } catch (Exception e) {
   196        log.error("Error while writing index", e);
   197      }
   198    }
   199  
   200    /**
   201     * Gets the page ID for the specified named page.
   202     *
   203     * @param name    a String
   204     * @return  a String instance, or null if no page exists
   205     *          with the specified name
   206     */
   207    public String getStaticPage(String name) {
             /* 
    P/P       *  Method: String getStaticPage(String)
              * 
              *  Preconditions:
              *    this.index != null
              * 
              *  Postconditions:
              *    init'ed(return_value)
              */
   208      return index.get(name);
   209    }
   210  
   211    /**
   212     * Gets the list of static page IDs.
   213     *
   214     * @return    a List<String>
   215     */
   216    public List<String> getStaticPages() {
             /* 
    P/P       *  Method: List getStaticPages()
              * 
              *  Preconditions:
              *    this.index != null
              * 
              *  Postconditions:
              *    return_value == &new LinkedList(getStaticPages#1)
              *    new LinkedList(getStaticPages#1) num objects == 1
              */
   217      return new LinkedList<String>(index.values());
   218    }
   219  
   220    /**
   221     * Determines whether a page with the specified permalink exists.
   222     *
   223     * @param name   the name as a String
   224     * @return  true if the page exists, false otherwise
   225     */
   226    public boolean contains(String name) {
             /* 
    P/P       *  Method: bool contains(String)
              * 
              *  Preconditions:
              *    this.index != null
              * 
              *  Postconditions:
              *    init'ed(return_value)
              */
   227      return index.containsKey(name);
   228    }
   229  
   230    /**
   231     * Gets the number of static pages.
   232     *
   233     * @return  an int
   234     */
   235    public int getNumberOfStaticPages() {
             /* 
    P/P       *  Method: int getNumberOfStaticPages()
              * 
              *  Preconditions:
              *    this.index != null
              * 
              *  Postconditions:
              *    init'ed(return_value)
              */
   236      return index.size();
   237    }
   238  
   239    private File getIndexFile() {
             /* 
    P/P       *  Method: File getIndexFile()
              * 
              *  Preconditions:
              *    this.blog != null
              * 
              *  Postconditions:
              *    return_value == &new File(getIndexFile#2)
              *    new File(getIndexFile#2) num objects == 1
              */
   240      File indexDirectory = new File(blog.getIndexesDirectory(), PAGES_INDEX_DIRECTORY_NAME);
   241      return new File(indexDirectory, NAME_TO_ID_INDEX_FILE_NAME);
   242    }
   243  
   244    private boolean lock() {
             /* 
    P/P       *  Method: bool lock()
              * 
              *  Preconditions:
              *    this.blog != null
              *    (soft) this.lockAttempts <= 232-2
              * 
              *  Presumptions:
              *    org.apache.commons.logging.LogFactory:getLog(...)@49 != null
              * 
              *  Postconditions:
              *    init'ed(return_value)
              *    this.lockAttempts == One-of{old this.lockAttempts, old this.lockAttempts + 1}
              *    (soft) init'ed(this.lockAttempts)
              * 
              *  Test Vectors:
              *    java.io.File:createNewFile(...)@248: {1}, {0}
              */
   245      File lockFile = new File(blog.getIndexesDirectory(), LOCK_FILE_NAME);
   246      boolean success = false;
   247      try {
   248        success = lockFile.createNewFile();
   249        if (!success) {
   250          lockAttempts++;
   251        }
   252      } catch (IOException ioe) {
   253        log.warn("Error while creating lock file", ioe);
   254      }
   255  
   256      return success;
   257    }
   258  
   259    private void unlock() {
             /* 
    P/P       *  Method: void unlock()
              * 
              *  Preconditions:
              *    this.blog != null
              * 
              *  Postconditions:
              *    this.lockAttempts == 0
              */
   260      File lockFile = new File(blog.getIndexesDirectory(), LOCK_FILE_NAME);
   261      lockFile.delete();
   262      lockAttempts = 0;
   263    }
   264  
   265  }








SofCheck Inspector Build Version : 2.22510
staticpageindex.java 2010-Jun-25 19:40:32
staticpageindex.class 2010-Jul-19 20:23:38