// BlogBridge -- RSS feed reader, manager, and web based service // Copyright (C) 2002-2007 by R. Pito Salas // // This program is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free Software Foundation; // either version 2 of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along with this program; // if not, write to the Free Software Foundation, Inc., 59 Temple Place, // Suite 330, Boston, MA 02111-1307 USA // // Contact: R. Pito Salas // mailto:pitosalas@users.sourceforge.net // More information: about BlogBridge // http://www.blogbridge.com // http://sourceforge.net/projects/blogbridge // // $Id: AbstractAutoSaver.java,v 1.3 2007/05/02 10:27:06 spyromus Exp $ // package com.salas.bb.core.autosave; import com.salas.bb.domain.IArticle; import com.salas.bb.domain.IFeed; import com.salas.bb.utils.StringUtils; import java.io.File; import java.text.MessageFormat; import java.util.Date; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; /** * Abstract implementation of the saver. */ abstract class AbstractAutoSaver { private ExecutorService executor; /** * Prepares the file using the given information. * * @param folder folder to save articles. * @param nameFormat article filename format. * @param feed parent feed. * @param title object title. * @param ext extension. * * @return file. */ protected File prepareFilename(String folder, String nameFormat, IFeed feed, String title, String ext) { String filename = replace(nameFormat, "title", "feed"); filename = replaceDate(filename, "current.date", 2); // Current Date Date currentDate = new Date(); // Feed Title String feedTitle = feed.getTitle(); feedTitle = escape(feedTitle); if (StringUtils.isEmpty(feedTitle)) feedTitle = "Unnamed Feed"; // Title title = escape(title); if (StringUtils.isEmpty(title)) title = "Article"; return new File(folder, MessageFormat.format(filename, title, feedTitle, currentDate) + ext); } /** * Replaces keys with the sequence of numbers. * * @param str string. * @param keys keys. * * @return result. */ protected static String replace(String str, String ... keys) { if (StringUtils.isNotEmpty(str)) { int i = 0; for (String key : keys) { str = str.replaceAll("\\{" + key + "\\}", "{" + (i++) + "}"); } } return str; } /** * Replaces date keys. * * @param str string. * @param key keys. * @param pos position to start counting. * * @return result. */ protected static String replaceDate(String str, String key, int pos) { return str.replaceAll("\\{" + key + "(,.+)?\\}", "{" + pos + ",date$1}"); } /** * Escapes characters for file names. * * @param str string. * * @return result. */ private static String escape(String str) { return str == null ? null : str.replaceAll("[<>\\?\"'\\*:/\\\\]", "_"); } /** * Invoked when a new article is added. * * @param article new article. * @param feed feed it was added (not necessarily parent, if it's search feed for ex.) */ protected abstract void onNewArticle(IArticle article, IFeed feed); /** * Returns common executor. * * @return executor. */ protected synchronized ExecutorService getExecutor() { if (executor == null) { executor = Executors.newFixedThreadPool(getExecutorThreadsNumber(), new ThreadFactory() { /** * Constructs a new <tt>Thread</tt>. Implementations may also initialize priority, name, daemon status, * <tt>ThreadGroup</tt>, etc. * * @param r a runnable to be executed by new thread instance * * @return constructed thread */ public Thread newThread(Runnable r) { return new Thread(r, getExecutorThreadName()); } }); } return executor; } /** * Returns the number of threads for executor. The default is <code>1</code>. * * @return the number of threads. */ protected int getExecutorThreadsNumber() { return 1; } /** * Returns the name of the executor thread. * * @return thread. */ protected abstract String getExecutorThreadName(); /** * Makes sure all directories are present and creates those that are not. * * @param file file. */ static void ensureAllDirsPresent(File file) { // Create all sub-directories if necessary File parentFile = file.getParentFile(); if (!parentFile.exists()) parentFile.mkdirs(); } }