/* * Created on Apr 8, 2004 * * This file is part of Thingamablog. ( http://thingamablog.sf.net ) * * Copyright (c) 2004, Bob Tantlinger All Rights Reserved. * * 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. */ package net.sf.thingamablog.blog; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Calendar; import java.util.Date; import java.util.Enumeration; import java.util.Hashtable; import java.util.Locale; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import net.atlanticbb.tantlinger.i18n.I18n; import net.atlanticbb.tantlinger.io.IOUtils; import net.sf.thingamablog.generator.PageGenerator; /** * Concrete implementation of a Weblog. * This is the standard Thingamablog Weblog class * * @author Bob Tantlinger */ public class TBWeblog extends Weblog { private static Logger logger = Logger.getLogger("net.sf.thingamablog.blog"); private static I18n i18n = I18n.getInstance("net.sf.thingamablog.blog"); //vaid chars for category page files names private static final String VALID_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789_-"; /** Constant indicating a monthly archive policy */ public static final int ARCHIVE_MONTHLY = 0; /** Constant indicating a weekly archive policy */ public static final int ARCHIVE_WEEKLY = 1; /** Constant indicating a "by n days" archive policy */ public static final int ARCHIVE_BY_DAY_INTERVAL = 2; private int archivePolicy = ARCHIVE_MONTHLY; private Date archiveBaseDate = new Date(0); private int archiveByDayInterval = 5; private ArchiveRange archives[] = new ArchiveRange[0]; private Locale locale = Locale.getDefault(); private PageGenerator generator = new PageGenerator(); private String frontPageFileName = "blog.html"; private String archiveIndexFileName = "archives.html"; private String rssFileName = "rss.xml"; private String archivesExtension = ".html"; private String categoriesExtension = ".html"; private String categoriesFeedExtension = ".rss"; private String entryPageExtension = ".html"; private String baseUrl = ""; private String archiveUrl = baseUrl; private String mediaUrl = baseUrl; private String basePath = "/"; private String archivePath = basePath; private String mediaPath = basePath; //private Vector outdatedTopLevelPages = new Vector(); private Vector outdatedCategoryPages = new Vector(); private Vector outdatedArchivePages = new Vector(); private Vector outdatedEntryPages = new Vector(); private boolean generateRssFeed = true; private boolean generateCategoryFeeds = false; private boolean generateArchiveIndex = true; private boolean generateEntryPages = true; private boolean shouldPublishAll; private TBTemplate mainTemplate; private TBTemplate archiveTemplate; private TBTemplate categoryTemplate; private TBTemplate arcIndexTemplate; private TBTemplate entryTemplate; private TBTemplate feedTemplate; private Vector templates = new Vector(5, 2); private String key; private File homeDir; private File tmplDir; private File outputDir; /** * Constructs a TBWeblog and creates the required directory structure * @param dir The home directory of the weblog. The directory * structure will be created in this directory. * @param key The unique key of this weblog */ public TBWeblog(File dir, String key) { this.key = key; init(dir); } /** * Constructs a TBWeblog and creates its directory structure * @param dir The home directory of the weblog. The directory structure * will be created in this directory */ public TBWeblog(File dir) { //unique key for this blog, it should never change key = System.currentTimeMillis() + ""; init(dir); } private void init(File dir) { //make our dirs if needed homeDir = new File(dir, key); if(!homeDir.exists() || homeDir.isFile()) homeDir.mkdirs(); tmplDir = new File(homeDir, "templates"); if(!tmplDir.exists() || tmplDir.isFile()) tmplDir.mkdir(); outputDir = new File(homeDir, "temp"); if(!outputDir.exists() || outputDir.isFile()) outputDir.mkdir(); webFilesDirectory = new File(homeDir, "web"); if(!webFilesDirectory.exists() || webFilesDirectory.isFile()) webFilesDirectory.mkdir(); //set the default arc list format generator.setArchiveRangeFormat("MMMM yyyy", false); //init the templates mainTemplate = new TBTemplate(new File(tmplDir, "main.template"), i18n.str("front_page")); templates.add(mainTemplate); archiveTemplate = new TBTemplate(new File(tmplDir, "archive.template"), i18n.str("archive")); templates.add(archiveTemplate); categoryTemplate = new TBTemplate(new File(tmplDir, "category.template"), i18n.str("category")); templates.add(categoryTemplate); entryTemplate = new TBTemplate(new File(tmplDir, "entry.template"), i18n.str("entry_pages")); templates.add(entryTemplate); arcIndexTemplate = new TBTemplate(new File(tmplDir, "index.template"), i18n.str("archive_index")); templates.add(arcIndexTemplate); feedTemplate = new TBTemplate(new File(tmplDir, "feed.template"), i18n.str("feed")); templates.add(feedTemplate); addWeblogListener(new TBWeblogListener()); addCategoryListener(new TBCategoryListener()); addAuthorListener(new TBAuthorListener()); } /** * Overridden from superclass to remove the TBWeblog dir structure */ public void deleteAll() throws BackendException { super.deleteAll(); //be careful about deleting dirs IOUtils.deleteRecursively(outputDir); IOUtils.deleteRecursively(tmplDir); if(webFilesDirectory.getParent().equals(homeDir.getAbsolutePath())) IOUtils.deleteRecursively(webFilesDirectory); new File(homeDir, "pack.properties").delete(); //won't delete if not empty homeDir.delete(); } /** * Gets the home directory of this TBWeblog. The home dir * contains the directory structure of the weblog * @return The home directory */ public File getHomeDirectory() { return homeDir; } /** * Gets the directory which contains the weblog's templates * @return The template directory */ public File getTemplateDirectory() { return tmplDir; } /** * Overridden from Weblog so that archives are rebuilt for the new backend */ public void setBackend(WeblogBackend backend) { super.setBackend(backend); try { updateArchives(); } catch(BackendException be){} } public String getKey() { return key; } /* (non-Javadoc) * @see net.sf.thingamablog.blog.Weblog#getTemplates() */ public Template[] getTemplates() { Template t[] = new Template[templates.size()]; for(int i = 0; i < t.length; i++) t[i] = (Template)templates.elementAt(i); return t; } /* (non-Javadoc) * @see net.sf.thingamablog.blog.Weblog#getArchives() */ public ArchiveRange[] getArchives() { if(archives == null) { try { updateArchives(); } catch(Exception ex) { logger.log(Level.WARNING, ex.getMessage(), ex); ex.printStackTrace(); } } return archives; } /** * Gets the PageGenerator for this TBWeblog * @return The page generator */ public PageGenerator getPageGenerator() { return generator; } /* (non-Javadoc) * @see net.sf.thingamablog.blog.Weblog#getCurrentEntries() */ public BlogEntry[] getCurrentEntries() throws BackendException { int limit = generator.getFrontPageLimit(); EntryEnumeration eEnum = backend.getEntries(getKey(), false); Vector v = new Vector(10, 2); int count = 0; while(eEnum.hasMoreEntries() && count < limit) { v.add(eEnum.nextEntry()); count++; } eEnum.close(); BlogEntry be[] = new BlogEntry[v.size()]; for(int i = 0; i < be.length; i++) be[i] = (BlogEntry)v.elementAt(i); return be; } public BlogEntry[] getExpiredEntries() throws BackendException { EntryEnumeration eEnum = backend.getEntriesBefore(getKey(), archiveBaseDate, false); Vector v = new Vector(10, 2); while(eEnum.hasMoreEntries()) { v.add(eEnum.nextEntry()); } eEnum.close(); BlogEntry be[] = new BlogEntry[v.size()]; for(int i = 0; i < be.length; i++) be[i] = (BlogEntry)v.elementAt(i); return be; } private class TBWeblogListener implements WeblogListener { public void entryAdded(WeblogEvent e) { System.out.println("Entry added"); BlogEntry be = e.getEntry(); Date d = be.getDate(); //is it a valid date? Date now = new Date(); if(!be.isDraft() && d.after(archiveBaseDate) && (d.before(now) || d.compareTo(now) == 0)) { //updateArchives(); ArchiveRange ar = getArchiveForDate(d); if(ar != null)//has archive for this range { //System.out.println("State changed"); addOutdatedArchive(ar); String cats[] = be.getCategories(); for(int i = 0; i < cats.length; i++) addOutdatedCategory(cats[i]); addOutdatedEntryID(new Long(be.getID())); outdatePrevNextEntries(be); } else { try { updateArchives(); } catch(Exception ex) { logger.log(Level.WARNING, ex.getMessage(), ex); ex.printStackTrace(); } shouldPublishAll = true; } } } public void entryUpdated(WeblogEvent e) { System.out.println("Entry updated"); try { BlogEntry oldEntry = e.getEntry(); BlogEntry newEntry = getEntry(oldEntry.getID()); if(oldEntry.isDraft() && newEntry.isDraft()) return; addOutdatedEntryID(new Long(newEntry.getID())); String cats[] = oldEntry.getCategories(); for(int i = 0; i < cats.length; i++) addOutdatedCategory(cats[i]); cats = newEntry.getCategories(); for(int i = 0; i < cats.length; i++) addOutdatedCategory(cats[i]); updateArchives(); ArchiveRange oar = getArchiveForDate(oldEntry.getDate()); ArchiveRange nar = getArchiveForDate(newEntry.getDate()); if(oar == null || nar == null) shouldPublishAll = true; else { addOutdatedArchive(oar); addOutdatedArchive(nar); outdatePrevNextEntries(newEntry); } } catch(Exception ex) { logger.log(Level.WARNING, ex.getMessage(), ex); ex.printStackTrace(); } } public void entryRemoved(WeblogEvent e) { System.out.println("Entry removed"); BlogEntry entry = e.getEntry(); outdatedEntryPages.remove(new Long(entry.getID())); if(entry.isDraft() || entry.getDate().before(getArchiveBaseDate())) return; String cats[] = entry.getCategories(); for(int i = 0; i < cats.length; i++) addOutdatedCategory(cats[i]); try { updateArchives(); ArchiveRange ar = getArchiveForDate(entry.getDate()); if(ar == null) shouldPublishAll = true; else { addOutdatedArchive(ar); outdatePrevNextEntries(entry); } } catch(Exception ex) { logger.log(Level.WARNING, ex.getMessage(), ex); ex.printStackTrace(); } } private void outdatePrevNextEntries(BlogEntry be) { try { BlogEntry e = getEntryAfter(be.getDate()); if(e != null) { addOutdatedEntryID(new Long(e.getID())); } e = getEntryBefore(be.getDate()); if(e != null) { addOutdatedEntryID(new Long(e.getID())); } } catch(Exception ex) { logger.log(Level.WARNING, ex.getMessage(), ex); ex.printStackTrace(); } } } private class TBCategoryListener implements CategoryListener { public void categoryAdded(CategoryEvent e) { catsChanged(); } public void categoryRenamed(CategoryEvent e) { catsChanged(); } public void categoryRemoved(CategoryEvent e) { catsChanged(); } private void catsChanged() { try { updateArchives(); } catch(Exception ex) { logger.log(Level.WARNING, ex.getMessage(), ex); ex.printStackTrace(); } shouldPublishAll = true; } } private class TBAuthorListener implements AuthorListener { public void authorAdded(AuthorEvent e) { //System.out.println("Author added " + e.getAuthor().getName()); //adding an author doesn't effect the state of the pages } public void authorUpdated(AuthorEvent e) { //System.out.println("Author updated " + e.getAuthor().getName()); shouldPublishAll = true; } public void authorRemoved(AuthorEvent e) { //System.out.println("Author removed " + e.getAuthor().getName()); shouldPublishAll = true; } } public Date getArchiveBaseDate() { return archiveBaseDate; } /** * Gets the n days that separate "by day" archives * @return n days */ public int getArchiveByDayInterval() { return archiveByDayInterval; } /** * Gets the archive policy of this weblog * @return one of ARCHIVE_MONTHLY, ARCHIVE_WEEKLY, or ARCHIVE_BY_DAY_INTERVAL */ public int getArchivePolicy() { return archivePolicy; } /** * Sets the base date for the archives. The weblog will not * generate entries that have a post date before this date * @param date The base date */ public void setArchiveBaseDate(Date d) { //set to 12:00 AM Calendar cal = Calendar.getInstance(); cal.setTime(d); cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0); archiveBaseDate = cal.getTime(); } /** * Sets the number of days to serparate "by n days" archives * @param i */ public void setArchiveByDayInterval(int i) { archiveByDayInterval = i; } /** * Sets the archive policy of the weblog * @param one of the constants: * ARCHIVE_MONTHLY, ARCHIVE_WEEKLY, or ARCHIVE_BY_DAY_INTERVAL */ public void setArchivePolicy(int i) { archivePolicy = i; } public String getUrlForEntry(BlogEntry b) { return getArchiveUrl() + getEntryPathPart(b) + getEntryFileName(b); } public String getUrlForCategory(String cat) { return getArchiveUrl() + getCategoryFileName(cat); } public String getUrlForArchive(ArchiveRange arc) { return getArchiveUrl() + getArchiveFileName(arc); } public String getUrlForWebFile(File f) throws IllegalArgumentException { if(!f.getAbsolutePath().startsWith(getWebFilesDirectory().getAbsolutePath())) throw new IllegalArgumentException("File " + f + " does not belong to blog [" + getTitle() + "]"); try { String url = f.toURL().toExternalForm(); String wurl = getWebFilesDirectory().toURL().toExternalForm(); int s = url.indexOf(wurl) + wurl.length(); return getBaseUrl() + url.substring(s, url.length()); } catch(Exception ex) { } return null; } private String getPathForEntry(BlogEntry b) { String arcPath = getArchivePath(); if(!arcPath.endsWith("/")) arcPath += "/"; return arcPath + getEntryPathPart(b); } private String getEntryPathPart(BlogEntry b) { Calendar cal = Calendar.getInstance(); cal.setTime(b.getDate()); String yr = cal.get(Calendar.YEAR) + ""; String mo = "0"; int month = cal.get(Calendar.MONTH) + 1; if(month < 10) mo += month + ""; else mo = month + ""; return yr + '/' + mo + '/'; } private String getEntryFileName(BlogEntry e) { return "entry_" + e.getID() + getEntryPageExtension(); } /** * Gets an archive for a date * @param d the date * @return an archive which the date falls between */ public ArchiveRange getArchiveForDate(Date d) { if(archives != null) { for(int i = 0; i < archives.length; i++) { Date s = archives[i].getStartDate(); Date e = archives[i].getExpirationDate(); if(s.before(d) && e.after(d)) return archives[i]; if(s.equals(d) || e.equals(d)) return archives[i]; } } System.out.println(d); return null; } /** * Gets the file name of the archive index page * @return */ public String getArchiveIndexFileName() { return archiveIndexFileName; } /** * Gets the server archive path * @return */ public String getArchivePath() { return archivePath; } /** * Gets the base URL of the archive pages * @return */ public String getArchiveUrl() { return archiveUrl; } /** * Gets the base server path * @return */ public String getBasePath() { return basePath; } /** * Gets the base URL of the weblog * @return */ public String getBaseUrl() { return baseUrl; } /** * Gets the file name of the front page * @return */ public String getFrontPageFileName() { return frontPageFileName; } /** * Gets the server path where media files are published to * @return */ public String getMediaPath() { return mediaPath; } /** * Gets the media URL * @return */ public String getMediaUrl() { return mediaUrl; } /** * Gets the file name of the weblog's front page feed * @return */ public String getRssFileName() { return rssFileName; } /** * @param string */ public void setArchiveIndexFileName(String string) { if(string != null && !string.equals("")) archiveIndexFileName = string; } /** * @param string */ public void setFrontPageFileName(String string) { if(string != null && !string.equals("")) frontPageFileName = string; } /** * Sets the URLs for the weblog * @param path The base server path * @param base The base URL * @param arcs The archive's base URL * @param media the media files URL */ public void setBlogUrls(String path, String base, String arcs, String media) { basePath = appendSlash(path);//append slash?? baseUrl = appendSlash(base); if(arcs.startsWith(baseUrl) && arcs.length() > baseUrl.length()) { archiveUrl = appendSlash(arcs); String pfix = archiveUrl.substring(baseUrl.length(), archiveUrl.length()); archivePath = basePath + pfix; } else { archiveUrl = baseUrl; archivePath = basePath; } if(media.startsWith(baseUrl) && media.length() > baseUrl.length()) { mediaUrl = appendSlash(media); String pfix = mediaUrl.substring(baseUrl.length(), mediaUrl.length()); mediaPath = basePath + pfix; } else { mediaUrl = baseUrl; mediaPath = basePath; } } /** * @param string */ public void setRssFileName(String string) { if(string != null && !string.equals("")) rssFileName = string; } public String getFrontPageUrl() { String url = getBaseUrl(); if(!url.endsWith("/")) url += "/"; return url + getFrontPageFileName(); } protected Hashtable weblogFiles(boolean pubAll) throws BackendException, IOException { Hashtable ht = new Hashtable(); if(pubAll) shouldPublishAll = true; //determine which archive pages to publish if(shouldPublishAll || archiveTemplate.getLastModifiedDate().after(lastPublishDate)) { outdatedArchivePages.removeAllElements(); updateArchives(); for(int i = 0; i < archives.length; i++) addOutdatedArchive(archives[i]); } //determine which category pages to publish if(shouldPublishAll || categoryTemplate.getLastModifiedDate().after(lastPublishDate) || (isGenerateCategoryFeeds() && feedTemplate.getLastModifiedDate().after(lastPublishDate))) { outdatedCategoryPages.removeAllElements(); String cats[] = getCategories(); for(int i = 0; i < cats.length; i++) { addOutdatedCategory(cats[i]); } } if(generateEntryPages && (shouldPublishAll || entryTemplate.getLastModifiedDate().after(lastPublishDate))) { outdatedEntryPages.removeAllElements(); try { EntryEnumeration eEnum = backend.getEntriesAfter(getKey(), getArchiveBaseDate(), true); while(eEnum.hasMoreEntries()) { BlogEntry ent = eEnum.nextEntry(); if(!ent.isDraft()) { addOutdatedEntryID(new Long(ent.getID())); } } eEnum.close(); } catch(Exception ex) { logger.log(Level.WARNING, ex.getMessage(), ex); ex.printStackTrace(); } } //generate top level pages //top level pages get published every time genTopLevelPages(ht); //generate archives String arcTmpl = archiveTemplate.load(); for(int i = 0; i < outdatedArchivePages.size(); i++) { ArchiveRange arc = (ArchiveRange)outdatedArchivePages.elementAt(i); File f = new File(outputDir, getArchiveFileName(arc)); OutputStream out = new FileOutputStream(f); generator.generatePage(this, arc, out, arcTmpl); out.close(); ht.put(f, getArchivePath()); } //generate categories String catTmpl = categoryTemplate.load(); String catFeedTmpl = null; if(isGenerateCategoryFeeds()) catFeedTmpl = feedTemplate.load(); for(int i = 0; i < outdatedCategoryPages.size(); i++) { String cat = outdatedCategoryPages.elementAt(i).toString(); //generate the cat page File f = new File(outputDir, getCategoryFileName(cat)); OutputStream out = new FileOutputStream(f); generator.generatePage(this, cat, out, catTmpl); out.close(); ht.put(f, getArchivePath()); //generate cat feed if(catFeedTmpl != null) { f = new File(outputDir, getCategoryFeedFileName(cat)); out = new FileOutputStream(f); generator.generatePage(this, cat, out, catFeedTmpl); out.close(); ht.put(f, getArchivePath()); } } //generate entry pages if(generateEntryPages) { String entryTmpl = entryTemplate.load(); for(int i = 0; i < outdatedEntryPages.size(); i++) { Long id = (Long)outdatedEntryPages.elementAt(i); try { BlogEntry be = getEntry(id.longValue()); File f = new File(outputDir, getEntryFileName(be)); OutputStream out = new FileOutputStream(f); generator.generatePage(this, be.getID(), out, entryTmpl); out.close(); ht.put(f, getPathForEntry(be)); } catch(Exception ex) { logger.log(Level.WARNING, ex.getMessage(), ex); ex.printStackTrace(); } } } return ht; } private void genTopLevelPages(Hashtable ht) throws IOException { //generate top level pages File f = new File(outputDir, frontPageFileName); OutputStream out = new FileOutputStream(f); generator.generatePage(this, PageGenerator.FRONT_PAGE, out, mainTemplate.load()); out.close(); ht.put(f, getBasePath()); if(generateArchiveIndex) { f = new File(outputDir, archiveIndexFileName); out = new FileOutputStream(f); generator.generatePage(this, PageGenerator.INDEX_PAGE, out, arcIndexTemplate.load()); out.close(); ht.put(f, getBasePath()); } if(generateRssFeed) { f = new File(outputDir, rssFileName); out = new FileOutputStream(f); generator.generatePage(this, PageGenerator.RSS_PAGE, out, feedTemplate.load()); out.close(); ht.put(f, getBasePath()); } } protected void publishComplete(Hashtable ht, boolean failed) { //delete the weblog files for(Enumeration e = ht.keys() ; e.hasMoreElements() ;) { try { File f = (File)e.nextElement(); f.delete(); } catch(ClassCastException cce){} } if(!failed) { System.out.println("clearing"); shouldPublishAll = false;//no pages need updated outdatedArchivePages.removeAllElements(); outdatedCategoryPages.removeAllElements(); outdatedEntryPages.removeAllElements(); } } private String appendSlash(String u) { if(!u.endsWith("/") && !u.equals( "" )) //Bug fix by John Montgomery u += "/"; return u; } /** * Adds an ArchiveRange to the list of archives to publish * @param ar - an outdated ArchiveRange */ public void addOutdatedArchive(ArchiveRange ar) { if(!outdatedArchivePages.contains(ar)) outdatedArchivePages.add(ar); } /** * * @param ar - an outdated ArchiveRange */ public void addOutdatedEntryID(Long id) { if(!outdatedEntryPages.contains(id)) outdatedEntryPages.add(id); } public long[] getOutdatedEntryIDs() { long ids[] = new long[outdatedEntryPages.size()]; for(int i = 0; i < ids.length; i++) ids[i] = ((Long)outdatedEntryPages.elementAt(i)).longValue(); return ids; } /** * Get the list of outdated ArchivesRanges * @return an array of ArchiveRanges */ public ArchiveRange[] getOutdatedArchives() { ArchiveRange ar[] = new ArchiveRange[outdatedArchivePages.size()]; for(int i = 0; i < ar.length; i++) ar[i] = (ArchiveRange)outdatedArchivePages.elementAt(i); return ar; } /** * Adds a category to the list of categories to publish * @param cat - a category */ public void addOutdatedCategory(String cat) { if(!outdatedCategoryPages.contains(cat)) outdatedCategoryPages.add(cat); } /** * Get the list of categories to publish * @return a string array */ public String[] getOutdatedCategories() { String s[] = new String[outdatedCategoryPages.size()]; for(int i = 0; i < s.length; i++) s[i] = outdatedCategoryPages.elementAt(i).toString(); return s; } /** * When set to true, the entries blog is published on when one of the publish * methods are called. When set to false, only outdated archives/categories * are published * @param b */ public void setPublishAll(boolean b) { shouldPublishAll = b; } /** * Indicates whether the weblog should publish everything * on the next publish session * @return - true if the blog is set to publish all, false otherwise */ public boolean isPublishAll() { return shouldPublishAll; } /** * Recalculates the weblog's archives * @throws BackendException If an error occurs while recalculating the archives */ public void updateArchives() throws BackendException { EntryEnumeration eEnum = backend.getEntriesAfter(getKey(), archiveBaseDate, true); ArchiveRange cur = null; Vector arcs = new Vector(20, 20); while(eEnum.hasMoreEntries()) { BlogEntry be = eEnum.nextEntry(); Date ts = be.getDate(); //System.out.println(ts); //current record greater than current page date if(cur == null || cur.getExpirationDate().compareTo(ts) < 0)//before { Date d1 = new Date(ts.getTime()); Calendar cal = Calendar.getInstance(); cal.setTime(ts); cal.add(Calendar.DATE, archiveByDayInterval - 1); Date d2 = cal.getTime(); if(archivePolicy == ARCHIVE_MONTHLY) { cal = Calendar.getInstance(); cal.setTime(d1); cal.set(Calendar.DAY_OF_MONTH, 1); d1 = cal.getTime(); cal.add(Calendar.MONTH, 1); cal.add(Calendar.DATE, -1); d2 = cal.getTime(); } else if(archivePolicy == ARCHIVE_WEEKLY) { cal = Calendar.getInstance(); cal.setTime(d1); //cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); //bug fix - in some countries Monday is the 1st day of the week cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek()); d1 = cal.getTime(); //cal.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY); cal.add(Calendar.DAY_OF_MONTH, 6); d2 = cal.getTime(); } cur = new ArchiveRange(d1, d2); arcs.add(cur); } } eEnum.close(); archives = new ArchiveRange[arcs.size()]; for(int i = 0; i < archives.length; i++) { archives[i] = (ArchiveRange)arcs.elementAt(i); //set the formatting archives[i].setFormatter( new java.text.SimpleDateFormat(generator.getArchiveRangeFormat()), generator.isSpanArcRange()); } } /** * Get the file name for a category * @param cat * @return */ public String getCategoryFileName(String cat) { return getCategoryFileName(cat, categoriesExtension); } public String getCategoryFeedFileName(String cat) { return getCategoryFileName(cat, categoriesFeedExtension); } public String getCategoryFileName(String cat, String ext) { char in[]=cat.toLowerCase().toCharArray(); char checkagainst[]=VALID_CHARS.toCharArray(); StringBuffer fileName = new StringBuffer(); for(int x = 0; x < in.length; x++) // check every inchar { for(int y = 0; y < checkagainst.length; y++) // aginst every validchar { if(in[x] == checkagainst[y]) fileName.append(in[x]); } } //no valid chars were found or the category name is too long if(fileName.length() == 0 || fileName.length() > 20) fileName = new StringBuffer(Integer.toString(Math.abs(cat.hashCode()))); fileName.append(ext); return "cat_" + fileName.toString(); } /** * Get the file name for a category * @param arc * @return */ public String getArchiveFileName(ArchiveRange arc) { java.text.SimpleDateFormat fileNameFormat = new java.text.SimpleDateFormat("MM-dd-yyyy"); String d1 = fileNameFormat.format(arc.getStartDate()); String d2 = fileNameFormat.format(arc.getExpirationDate()); return d1 + "_" + d2 + archivesExtension; } /** * Indicates whether the weblog should generate the archive index page * @return */ public boolean isGenerateArchiveIndex() { return generateArchiveIndex; } /** * Indicates whether the weblog should generate the syndication feed * @return */ public boolean isGenerateRssFeed() { return generateRssFeed; } /** * Indicates whether the weblog should generate entry pages * @return */ public boolean isGenerateEntryPages() { return generateEntryPages; } /** * @param b */ public void setGenerateArchiveIndex(boolean b) { generateArchiveIndex = b; if(b) { if(!templates.contains(arcIndexTemplate)) templates.add(arcIndexTemplate); } else templates.remove(arcIndexTemplate); } /** * @param b */ public void setGenerateRssFeed(boolean b) { generateRssFeed = b; if(b) { if(!templates.contains(feedTemplate)) templates.add(feedTemplate); } else { if(!isGenerateCategoryFeeds()) templates.remove(feedTemplate); } } /** * @param generateCategoryFeeds The generateCategoryFeeds to set. */ public void setGenerateCategoryFeeds(boolean b) { generateCategoryFeeds = b; if(b) { if(!templates.contains(feedTemplate)) templates.add(feedTemplate); } else { if(!isGenerateRssFeed()) templates.remove(feedTemplate); } } /** * @return Returns the generateCategoryFeeds. */ public boolean isGenerateCategoryFeeds() { return generateCategoryFeeds; } public void setGenerateEntryPages(boolean b) { generateEntryPages = b; if(b) { if(!templates.contains(entryTemplate)) templates.add(entryTemplate); } else templates.remove(entryTemplate); } /** * Gets the locale of the weblog. * The locale specifies how dates should be formatted * @return */ public Locale getLocale() { return locale; } /** * Sets the locale of the weblog * @param locale */ public void setLocale(Locale locale) { this.locale = locale; } /** * Gets the extension of archive pages * @return */ public String getArchivesExtension() { return archivesExtension; } /** * Gets the extension of category pages * @return */ public String getCategoriesExtension() { return categoriesExtension; } /** * Sets the extension of archive pages * @param string */ public void setArchivesExtension(String string) { if(!string.startsWith(".")) string = "." + string; archivesExtension = string; } /** * Sets the extension of category pages * @param string */ public void setCategoriesExtension(String string) { if(!string.startsWith(".")) string = "." + string; categoriesExtension = string; } public void setEntryPageExtension(String string) { if(!string.startsWith(".")) string = "." + string; entryPageExtension = string; } public String getEntryPageExtension() { return entryPageExtension; } /** * @return Returns the categoriesFeedExtension. */ public String getCategoriesFeedExtension() { return categoriesFeedExtension; } /** * @param categoriesFeedExtension The categoriesFeedExtension to set. */ public void setCategoriesFeedExtension(String ext) { if(!ext.startsWith(".")) ext = "." + ext; categoriesFeedExtension = ext; } public TemplatePack getTemplatePack() throws IOException { try { DiskTemplatePack pack = new DiskTemplatePack(getHomeDirectory()); return pack; } catch(IllegalArgumentException ex) { ex.printStackTrace(); } return null; } }