/* * $Id: ContentRSSProducer.java,v 1.9 2007/11/13 09:31:48 laddi Exp $ * Created on Sep 13, 2006 * * Copyright (C) 2006 Idega Software hf. All Rights Reserved. * * This software is the proprietary information of Idega hf. * Use is subject to license terms. */ package com.idega.content.business; import java.io.IOException; import java.rmi.RemoteException; import java.util.ArrayList; import java.util.Date; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.ServletException; import org.apache.commons.httpclient.HttpException; import org.apache.webdav.lib.WebdavResources; import com.idega.block.rss.business.RSSAbstractProducer; import com.idega.block.rss.business.RSSProducer; import com.idega.block.rss.data.RSSRequest; import com.idega.slide.business.IWContentEvent; import com.idega.slide.business.IWSlideChangeListener; import com.idega.slide.util.WebdavExtendedResource; import com.idega.util.CoreConstants; import com.idega.util.FileUtil; import com.sun.syndication.feed.synd.SyndContent; import com.sun.syndication.feed.synd.SyndContentImpl; import com.sun.syndication.feed.synd.SyndEntry; import com.sun.syndication.feed.synd.SyndEntryImpl; import com.sun.syndication.feed.synd.SyndFeed; import com.sun.syndication.feed.synd.SyndFeedImpl; /** * This RSSProducer can produce rss files for folders in slide. Its RSSProducer identifier is by default "content". * The rss file for a folder is called "content.xml" and is stored in a hidden folder called ".rss" under the folder that was requested. * An IWSlideChangeListener see's to it that a cachemap containing which rssfiles are up to date is invalidated. * * Last modified: $Date: 2007/11/13 09:31:48 $ by $Author: laddi $ * * @author <a href="mailto:eiki@idega.com">eiki</a> * @version $Revision: 1.9 $ */ public class ContentRSSProducer extends RSSAbstractProducer implements RSSProducer, IWSlideChangeListener { public static final String RSS_FOLDER_NAME = ".rss"; public static final String RSS_FILE_NAME = "content.xml"; private Map rssFileURIsCacheMap = new HashMap(); public ContentRSSProducer() { super(); } /** * @see com.idega.block.rss.business.RSSProducer */ @Override public void handleRSSRequest(RSSRequest rssRequest) throws IOException { //Take the request uri and get the extrauri part of it //the extra part refers to a folder and should end with a "/", add it if missing //Check with slidesession if the folder exists, this will return false if you don't have the right priviledges or the folder does not exist //If it exists (you there for have the rights) then check if the rss file exists in the hidden folder ".rss/content.xml" //If the feed file exists, dispatch to it //If not, create it and then dispatch to it. String uri = fixURI(rssRequest); String feedFile = uri+RSS_FOLDER_NAME+"/"+RSS_FILE_NAME; String realURI = CoreConstants.WEBDAV_SERVLET_URI+feedFile; try { //This is an important check since it will also determin if the user can view the folder if(this.isAFolderInSlide(uri,rssRequest)){ //for testing // if(this.existsInSlide(feedFile,rssRequest) && false ){ //Both check if the file has been created and if the uri is cached. //The uri is decached when something in the folder changes so the rss file gets regenerated if(this.existsInSlide(feedFile,rssRequest) && rssFileURIsCacheMap.containsKey(uri)){ this.dispatch(realURI, rssRequest); } else{ //generate rss and store and the dispatch to it //and add a listener to that directory try { createRSSFile(rssRequest, uri); rssFileURIsCacheMap.put(uri,realURI); this.dispatch(CoreConstants.WEBDAV_SERVLET_URI+feedFile, rssRequest); } catch (Exception e) { throw new IOException(e.getMessage()); } } } else{ //throw some exception? //this.dispatch(uri, rssRequest); //FOR NOW IT DOES NOTHING SO NOT TO WASTE CPU OR MEMORY FOR BOGUS REQUESTS } } catch (ServletException e) { e.printStackTrace(); } } /** * @param rssRequest * @return */ protected String fixURI(RSSRequest rssRequest) { String uri = "/"+rssRequest.getExtraUri(); if(!uri.endsWith("/")){ uri+="/"; } if(!uri.startsWith(CoreConstants.PATH_FILES_ROOT)){ uri = CoreConstants.PATH_FILES_ROOT+uri; } return uri; } /** * @param rssRequest * @param uri * @throws HttpException * @throws IOException * @throws RemoteException */ protected synchronized void createRSSFile(RSSRequest rssRequest, String uri) throws HttpException, IOException, RemoteException { WebdavExtendedResource folder = this.getIWSlideSession(rssRequest).getWebdavResource(uri); WebdavResources resources = folder.listWithDeltaV(); Enumeration children = resources.getResources(); SyndFeed feed = new SyndFeedImpl(); feed.setTitle(uri+" : Generated by IdegaWeb ePlatform"); feed.setLink(this.getServerURLWithURI(rssRequest.getRequestWrapped().getServletPath()+"/"+rssRequest.getIdentifier()+uri,rssRequest)); feed.setDescription("File feed generated by IdegaWeb ePlatform, Idega Software, http://www.idega.com. This feed lists the latest documents from the folder: "+uri); feed.setPublishedDate(new Date()); feed.setEncoding(CoreConstants.ENCODING_UTF8); feed.setCopyright("Idega Software"); List entries = new ArrayList(); SyndEntry entry; SyndContent description; while (children.hasMoreElements()) { WebdavExtendedResource resource = (WebdavExtendedResource) children.nextElement(); String fileName = resource.getDisplayName(); if(! this.getIWSlideService(rssRequest).isHiddenFile(fileName)){ boolean isFolder = resource.isCollection(); entry = new SyndEntryImpl(); entry.setTitle(fileName); if(isFolder){ entry.setLink(this.getServerURLWithURI("/rss"+resource.getPath(),rssRequest)); } else{ entry.setLink(this.getServerURLWithURI(resource.getPath(),rssRequest)); } long creationDate = resource.getCreationDate(); long modifiedDate = resource.getGetLastModified(); if(creationDate==0){ creationDate = modifiedDate; } entry.setPublishedDate(new Date(creationDate)); entry.setUpdatedDate(new Date(modifiedDate)); description = new SyndContentImpl(); description.setType("text/html"); if(!isFolder){ if(resource.getGetContentType().indexOf("image")>-1){ description.setValue("<img src='"+this.getServerURLWithURI(resource.getPath(),rssRequest)+"'/><br/>Size : "+FileUtil.getHumanReadableSize(resource.getGetContentLength())+"<br/>Content type: "+resource.getGetContentType()); } else{ description.setValue("Size : "+FileUtil.getHumanReadableSize(resource.getGetContentLength())+"</br>Content type: "+resource.getGetContentType()); } } else{ description.setValue("Folder"); } entry.setDescription(description); entries.add(entry); } } feed.setEntries(entries); String feedXML = this.getRSSBusiness().convertFeedToRSS2XMLString(feed); //deletes the previous version this.getIWSlideService(rssRequest).uploadFileAndCreateFoldersFromStringAsRoot(uri+RSS_FOLDER_NAME+"/", RSS_FILE_NAME, feedXML,this.getRSSContentType(),true); } /** * @return Returns the rssFileURIsCacheMap. */ protected Map getRssFileURIsCacheMap() { return rssFileURIsCacheMap; } /** * @param rssFileURIsCacheMap The rssFileURIsCacheMap to set. */ protected void setRssFileURIsCacheMap(Map rssFileURIsCacheMap) { this.rssFileURIsCacheMap = rssFileURIsCacheMap; } public void onSlideChange(IWContentEvent contentEvent) { // On a file change this code checks if an rss file already exists and if so updates it (overwrites) with a new folder list String URI = contentEvent.getContentEvent().getUri(); int index = URI.lastIndexOf("/"); URI = URI.substring(0,index+1); getRssFileURIsCacheMap().remove(URI); } }