Package net.sourceforge.pebble.dao.file

Source Code of net.sourceforge.pebble.dao.file.FileBlogEntryDAO

/*
* Copyright (c) 2003-2011, Simon Brown
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*   - Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*
*   - Redistributions in binary form must reproduce the above copyright
*     notice, this list of conditions and the following disclaimer in
*     the documentation and/or other materials provided with the
*     distribution.
*
*   - Neither the name of Pebble nor the names of its contributors may
*     be used to endorse or promote products derived from this software
*     without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

package net.sourceforge.pebble.dao.file;

import net.sourceforge.pebble.dao.BlogEntryDAO;
import net.sourceforge.pebble.dao.PersistenceException;
import net.sourceforge.pebble.domain.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

public class FileBlogEntryDAO implements BlogEntryDAO {

  /** timezone to use for calculating paths on disk, etc */
  private static final TimeZone GMT = TimeZone.getTimeZone("GMT");

  /**
   * the log used by this class
   */
  private static Log log = LogFactory.getLog(FileBlogEntryDAO.class);

  public FileBlogEntryDAO() {
  }

  /** the date/time format used when persisting dates */
  static final String OLD_PERSISTENT_DATETIME_FORMAT = "dd MMM yyyy HH:mm:ss z";
  static final String NEW_PERSISTENT_DATETIME_FORMAT = "dd MMM yyyy HH:mm:ss:S Z";
  static final String REGEX_FOR_YEAR = "\\d\\d\\d\\d";

  /**
   * Loads a specific blog entry.
   *
   * @param blogEntryId   the blog entry ID
   * @return a BlogEntry instance
   * @throws net.sourceforge.pebble.dao.PersistenceException
   *          if the specified blog entry cannot be loaded
   */
  public BlogEntry loadBlogEntry(Blog blog, String blogEntryId) throws PersistenceException {
    File path = new File(getPath(blog, blogEntryId, GMT));
    File file = new File(path, blogEntryId + ".xml");
    return loadBlogEntry(blog, file);
  }

  /**
   * Loads a blog entry from the specified file.
   *
   * @param source    the File pointing to the source
   * @throws net.sourceforge.pebble.dao.PersistenceException
   *          if the blog entry can't be loaded
   */
  private BlogEntry loadBlogEntry(Blog blog, File source) throws PersistenceException {
    if (source.exists()) {
      log.debug("Loading " + source.getAbsolutePath());
      BlogEntry blogEntry = new BlogEntry(blog);

      try {
        DefaultHandler handler = new BlogEntryHandler(blogEntry);
        SAXParserFactory saxFactory = SAXParserFactory.newInstance();
        saxFactory.setValidating(false);
        saxFactory.setNamespaceAware(true);
        SAXParser parser = saxFactory.newSAXParser();
        parser.parse(source, handler);

      } catch (Exception e) {
        log.error(e.getMessage() + " while loading blog enty from " + source.getAbsolutePath(), e);
        e.printStackTrace();
        throw new PersistenceException(e.getMessage());
      }

      return blogEntry;
    } else {
      return null;
    }
  }

  /**
   * Loads all blog entries.
   *
   * @param blog the Blog to load all entries for
   * @return a List of BlogEntry objects
   * @throws net.sourceforge.pebble.dao.PersistenceException
   *          if the blog entries cannot be loaded
   */
  public Collection<BlogEntry> loadBlogEntries(Blog blog) throws PersistenceException {
    List<BlogEntry> list = new ArrayList<BlogEntry>();

    File root = new File(blog.getRoot());
    File years[] = root.listFiles(new FourDigitFilenameFilter());
    for (File year : years) {
      File months[] = year.listFiles(new TwoDigitFilenameFilter());
      for (File month : months) {
        File days[] = month.listFiles(new TwoDigitFilenameFilter());
        for (File day : days) {
          File blogEntryFiles[] = day.listFiles(new BlogEntryFilenameFilter());
          for (File blogEntryFile : blogEntryFiles) {
            list.add(loadBlogEntry(blog, blogEntryFile));
          }
        }
      }
    }

    return list;
  }

  /**
   * Stores the specified blog entry.
   *
   * @param blogEntry the blog entry to store
   * @throws PersistenceException if something goes wrong storing the entry
   */
  public void storeBlogEntry(BlogEntry blogEntry) throws PersistenceException {
    File outputDir = new File(getPath(blogEntry.getBlog(), blogEntry.getId(), GMT));
    if (!outputDir.exists()) {
      outputDir.mkdirs();
    }

    File outputFile = new File(outputDir, blogEntry.getId() + ".xml");
    storeBlogEntry(blogEntry, outputFile);
  }


  /**
   * Stores a blog entry to the specified file.
   *
   * @param blogEntry   the BlogEntry that is being stored
   * @param destination the File pointing to the destination
   * @throws PersistenceException if something goes wrong storing the entry
   */
  private void storeBlogEntry(BlogEntry blogEntry, File destination) throws PersistenceException {
    File backupFile = new File(destination.getParentFile(), destination.getName() + ".bak");
    try {
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      factory.setValidating(false);
      factory.setNamespaceAware(true);
      factory.setIgnoringElementContentWhitespace(true);
      factory.setIgnoringComments(true);

      DocumentBuilder builder = factory.newDocumentBuilder();
      Document doc = builder.newDocument();

      Element root = doc.createElement("blogEntry");
      doc.appendChild(root);

      Element titleNode = doc.createElement("title");
      Element subtitleNode = doc.createElement("subtitle");
      Element excerptNode = doc.createElement("excerpt");
      Element bodyNode = doc.createElement("body");
      Element categoryNode;
      Element tagsNode = doc.createElement("tags");
      Element dateNode = doc.createElement("date");
      Element timeZoneNode = doc.createElement("timeZone");
      Element stateNode = doc.createElement("state");
      Element authorNode = doc.createElement("author");
      Element staticNameNode = doc.createElement("staticName");
      Element commentsEnabledNode = doc.createElement("commentsEnabled");
      Element trackBacksEnabledNode = doc.createElement("trackBacksEnabled");
      Element attachmentNode = doc.createElement("attachment");

      root.appendChild(titleNode);
      root.appendChild(subtitleNode);
      root.appendChild(excerptNode);
      root.appendChild(bodyNode);
      root.appendChild(dateNode);
      root.appendChild(timeZoneNode);
      root.appendChild(stateNode);
      root.appendChild(authorNode);
      root.appendChild(staticNameNode);

      if (blogEntry.isAggregated()) {
        Element permalinkNode = doc.createElement("originalPermalink");
        permalinkNode.appendChild(doc.createTextNode(blogEntry.getOriginalPermalink()));
        root.appendChild(permalinkNode);
      }

      titleNode.appendChild(doc.createTextNode(blogEntry.getTitle()));
      subtitleNode.appendChild(doc.createTextNode(blogEntry.getSubtitle()));
      bodyNode.appendChild(doc.createCDATASection(blogEntry.getBody()));

      if (blogEntry.getExcerpt() != null) {
        excerptNode.appendChild(doc.createCDATASection(blogEntry.getExcerpt()));
      }

      root.appendChild(commentsEnabledNode);
      commentsEnabledNode.appendChild(doc.createTextNode("" + blogEntry.isCommentsEnabled()));

      root.appendChild(trackBacksEnabledNode);
      trackBacksEnabledNode.appendChild(doc.createTextNode("" + blogEntry.isTrackBacksEnabled()));

      Iterator it = blogEntry.getCategories().iterator();
      Category category;
      while (it.hasNext()) {
        category = (Category) it.next();
        categoryNode = doc.createElement("category");
        categoryNode.appendChild(doc.createTextNode(category.getId()));
        root.appendChild(categoryNode);
      }

      if (blogEntry.getTags() != null) {
        root.appendChild(tagsNode);
        tagsNode.appendChild(doc.createTextNode(blogEntry.getTags()));
      }

      if (blogEntry.getAuthor() != null) {
        authorNode.appendChild(doc.createTextNode(blogEntry.getAuthor()));
      }

      SimpleDateFormat sdf = new SimpleDateFormat(NEW_PERSISTENT_DATETIME_FORMAT, Locale.ENGLISH);
      sdf.setTimeZone(GMT);
      dateNode.appendChild(doc.createTextNode(sdf.format(blogEntry.getDate())));

      timeZoneNode.appendChild(doc.createTextNode(blogEntry.getTimeZoneId()));

      stateNode.appendChild(createTextNode(doc, blogEntry.getState().getName()));

      Attachment attachment = blogEntry.getAttachment();
      if (attachment != null) {
        root.appendChild(attachmentNode);
        Element attachmentUrlNode = doc.createElement("url");
        attachmentUrlNode.appendChild(createTextNode(doc, attachment.getUrl()));
        attachmentNode.appendChild(attachmentUrlNode);
        Element attachmentSizeNode = doc.createElement("size");
        attachmentSizeNode.appendChild(createTextNode(doc, "" + attachment.getSize()));
        attachmentNode.appendChild(attachmentSizeNode);
        Element attachmentTypeNode = doc.createElement("type");
        attachmentTypeNode.appendChild(createTextNode(doc, attachment.getType()));
        attachmentNode.appendChild(attachmentTypeNode);
      }

      // and now store the comments
      it = blogEntry.getComments().iterator();
      while (it.hasNext()) {
        Comment comment = (Comment) it.next();
        storeComment(comment, doc, root);
      }

      // and finally the trackbacks
      it = blogEntry.getTrackBacks().iterator();
      while (it.hasNext()) {
        TrackBack trackBack = (TrackBack) it.next();
        storeTrackBack(trackBack, doc, root);
      }

      // write the XMl to a String, and then write this string to a file
      // (if the XML format fails, we don't corrupt the file)
      StringWriter sw = new StringWriter();
      Source source = new DOMSource(doc);
      Result result = new StreamResult(sw);
      Transformer xformer = TransformerFactory.newInstance().newTransformer();
      xformer.setOutputProperty(OutputKeys.METHOD, "xml");
      xformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
      xformer.setOutputProperty(OutputKeys.MEDIA_TYPE, "text/xml");
      xformer.setOutputProperty(OutputKeys.CDATA_SECTION_ELEMENTS, "body");
      xformer.setOutputProperty(OutputKeys.INDENT, "yes");
      xformer.transform(source, result);

      // now take a backup of the correct file
      if (destination.exists() && destination.length() > 0) {
        log.debug("Backing up to " + backupFile.getAbsolutePath());
        destination.renameTo(backupFile);
      }

      log.debug("Saving to " + destination.getAbsolutePath());
      BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(destination), "UTF-8"));
      bw.write(sw.getBuffer().toString());
      bw.flush();
      bw.close();
    } catch (Exception e) {
      log.error(e.getMessage(), e);
      e.printStackTrace();
      throw new PersistenceException(e.getMessage());
    }
  }

  /**
   * Helper method to store an individual comment.
   *
   * @param comment the Comment being stored
   * @param doc     the Document into which the comment is to be inserted
   * @param root    the root Node for the comment
   * @throws java.lang.Exception if something goes wrong
   */
  private void storeComment(Comment comment, Document doc, Node root) throws Exception {
    Element commentNode = doc.createElement("comment");
    root.appendChild(commentNode);

    Element titleNode = doc.createElement("title");
    Element bodyNode = doc.createElement("body");
    Element authorNode = doc.createElement("author");
    Element emailNode = doc.createElement("email");
    Element websiteNode = doc.createElement("website");
    Element avatarNode = doc.createElement("avatar");
    Element ipAddressNode = doc.createElement("ipAddress");
    Element dateNode = doc.createElement("date");
    Element parentNode = doc.createElement("parent");
    Element stateNode = doc.createElement("state");
    Element authenticatedNode = doc.createElement("authenticated");

    commentNode.appendChild(titleNode);
    commentNode.appendChild(bodyNode);
    commentNode.appendChild(authorNode);
    commentNode.appendChild(emailNode);
    commentNode.appendChild(websiteNode);
    commentNode.appendChild(avatarNode);
    commentNode.appendChild(ipAddressNode);
    commentNode.appendChild(dateNode);
    commentNode.appendChild(stateNode);
    commentNode.appendChild(authenticatedNode);

    titleNode.appendChild(createTextNode(doc, comment.getTitle()));
    bodyNode.appendChild(createCDATASection(doc, comment.getBody()));
    authorNode.appendChild(createTextNode(doc, comment.getAuthor()));
    emailNode.appendChild(createTextNode(doc, comment.getEmail()));
    websiteNode.appendChild(createTextNode(doc, comment.getWebsite()));
    avatarNode.appendChild(createTextNode(doc, comment.getAvatar()));
    ipAddressNode.appendChild(createTextNode(doc, comment.getIpAddress()));
    SimpleDateFormat sdf = new SimpleDateFormat(NEW_PERSISTENT_DATETIME_FORMAT, Locale.ENGLISH);
    sdf.setTimeZone(GMT);
    dateNode.appendChild(createTextNode(doc, sdf.format(comment.getDate())));
    stateNode.appendChild(createTextNode(doc, comment.getState().getName()));
    authenticatedNode.appendChild(createTextNode(doc, "" + comment.isAuthenticated()));

    if (comment.getParent() != null) {
      commentNode.appendChild(parentNode);
      parentNode.appendChild(createTextNode(doc, "" + comment.getParent().getId()));
    }
  }

  private Node createCDATASection(Document doc, String text) {
    if (text != null) {
      return doc.createCDATASection(text);
    } else {
      return doc.createCDATASection("");
    }
  }

  private Node createTextNode(Document doc, String text) {
    if (text != null) {
      return doc.createTextNode(text);
    } else {
      return doc.createTextNode("");
    }
  }

  /**
   * Helper method to store an individual trackback.
   *
   * @param trackBack the TrackBack being stored
   * @param doc       the Document into which the trackback is to be inserted
   * @param root      the root Node for the comment
   * @throws java.lang.Exception if something goes wrong
   */
  private void storeTrackBack(TrackBack trackBack, Document doc, Node root) throws Exception {
    Element commentNode = doc.createElement("trackback");
    root.appendChild(commentNode);

    Element titleNode = doc.createElement("title");
    Element excerptNode = doc.createElement("excerpt");
    Element urlNode = doc.createElement("url");
    Element blogNameNode = doc.createElement("blogName");
    Element ipAddressNode = doc.createElement("ipAddress");
    Element dateNode = doc.createElement("date");
    Element stateNode = doc.createElement("state");

    commentNode.appendChild(titleNode);
    commentNode.appendChild(excerptNode);
    commentNode.appendChild(urlNode);
    commentNode.appendChild(blogNameNode);
    commentNode.appendChild(ipAddressNode);
    commentNode.appendChild(dateNode);
    commentNode.appendChild(stateNode);

    titleNode.appendChild(createTextNode(doc, trackBack.getTitle()));
    excerptNode.appendChild(createCDATASection(doc, trackBack.getExcerpt()));
    urlNode.appendChild(createTextNode(doc, trackBack.getUrl()));
    blogNameNode.appendChild(createTextNode(doc, trackBack.getBlogName()));
    ipAddressNode.appendChild(createTextNode(doc, trackBack.getIpAddress()));
    SimpleDateFormat sdf = new SimpleDateFormat(NEW_PERSISTENT_DATETIME_FORMAT, Locale.ENGLISH);
    sdf.setTimeZone(GMT);
    dateNode.appendChild(doc.createTextNode(sdf.format(trackBack.getDate())));
    stateNode.appendChild(createTextNode(doc, trackBack.getState().getName()));
  }

  /**
   * Removes the specified blog entry.
   *
   * @param blogEntry the blog entry to remove
   * @throws PersistenceException if something goes wrong removing the entry
   */
  public void removeBlogEntry(BlogEntry blogEntry) throws PersistenceException {
    File path = new File(getPath(blogEntry.getBlog(), blogEntry.getId(), GMT));
    File file = new File(path, blogEntry.getId() + ".xml");
    log.debug("Removing " + blogEntry.getGuid());

    boolean success = file.delete();
    if (!success) {
      throw new PersistenceException("Deletion of blog entry " + blogEntry.getGuid() + " failed");
    }
  }

  /**
   * Given a blog and blog entry ID, this method determines the path where
   * that blog entry is stored.
   *
   * @param blog    the owning Blog
   * @param blogEntryId   the ID of the blog entry
   * @return  a String of the form blogroot/yyyy/MM/dd
   */
  public String getPath(Blog blog, String blogEntryId, TimeZone timeZone) {
    DateFormat year = new SimpleDateFormat("yyyy");
    year.setTimeZone(timeZone);
    DateFormat month = new SimpleDateFormat("MM");
    month.setTimeZone(timeZone);
    DateFormat day = new SimpleDateFormat("dd");
    day.setTimeZone(timeZone);

    long dateInMillis = Long.parseLong(blogEntryId);
    Date date = new Date(dateInMillis);

    StringBuffer buf = new StringBuffer();
    buf.append(blog.getRoot());
    buf.append(File.separator);
    buf.append(year.format(date));
    buf.append(File.separator);
    buf.append(month.format(date));
    buf.append(File.separator);
    buf.append(day.format(date));

    return buf.toString();
  }

}
TOP

Related Classes of net.sourceforge.pebble.dao.file.FileBlogEntryDAO

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.