staticpageindex.java

### 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