/* ==================================================================
* Created [2009-4-27 下午11:32:55] by Jon.King
* ==================================================================
* TSS
* ==================================================================
* mailTo:jinpujun@hotmail.com
* Copyright (c) Jon.King, 2009-2012
* ==================================================================
*/
package com.jinhe.tss.cms.publish;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired;
import com.jinhe.tss.cms.CMSConstants;
import com.jinhe.tss.cms.entity.Article;
import com.jinhe.tss.cms.entity.Channel;
import com.jinhe.tss.cms.entity.WordsFilter;
import com.jinhe.tss.cms.helper.ArticleHelper;
import com.jinhe.tss.cms.service.IChannelService;
import com.jinhe.tss.core.common.progress.Progress;
import com.jinhe.tss.core.common.progress.ProgressManager;
import com.jinhe.tss.core.common.progress.Progressable;
import com.jinhe.tss.core.exception.BusinessException;
import com.jinhe.tss.core.util.EasyUtils;
import com.jinhe.tss.core.util.FileHelper;
import com.jinhe.tss.um.UMConstants;
import com.jinhe.tss.um.permission.PermissionHelper;
/**
* <p> PublishManger.java </p>
* 文章发布,以及全文检索索引发布
*/
public class PublishManger implements Progressable {
public static final int PAGE_SIZE = 100; // 每页记录个数
@Autowired private IChannelService channelService;
/**
* 发布文章(注:完全发布的话已经发布的也重新发布,增量发布则只发布流程为“待发布”的文章)
*
* @param channelId 栏目ID
* @param category 1:增量发布 2:完全发布
*/
public String publishArticle(Long channelId, String category) {
// 判断是否对该栏目有发布权限
checkPublishPermission(channelId);
int totalRows = channelService.getTotalRows4Publish(channelId, category);
int totalPageNum = totalRows / PAGE_SIZE ;
if( totalRows % PAGE_SIZE > 0 ) {
totalPageNum = totalPageNum + 1;
}
Map<String, Object> paramsMap = new HashMap<String, Object>();
paramsMap.put("channelId", channelId);
paramsMap.put("category", category);
paramsMap.put("totalPageNum", totalPageNum);
ProgressManager manager = new ProgressManager(this, totalRows, paramsMap);
return manager.execute();
}
/**
* 判断是否对该栏目有发布权限
*/
public void checkPublishPermission(Long channelId) {
String appId = UMConstants.TSS_APPLICATION_ID;
String resourceType = CMSConstants.RESOURCE_TYPE_CHANNEL;
String operation = CMSConstants.OPERATION_PUBLISH;
List<Long> permitedList = PermissionHelper.getInstance().getResourceIdsByOperation(appId, resourceType, operation);
if ( !permitedList.contains(channelId) ) {
Channel channel = channelService.getChannelById(channelId);
throw new BusinessException("您没有发布本栏目(站点)【id = " + channelId + ", name = " + channel.getName() + "】的权限!");
}
}
public void execute(Map<String, Object> params, final Progress progress) {
Long channelId = (Long) params.get("channelId");
String category = (String) params.get("category");
Integer totalPageNum = (Integer) params.get("totalPageNum");
Long siteId = channelService.getSiteIdByChannelId(channelId);
// 分页发布文章
for (int page = 1; page <= totalPageNum; page++) {
List<?> pageArticleList = channelService.getPageArticleList(channelId, page, PAGE_SIZE, category);
channelService.publishArticle(pageArticleList, siteId);
progress.add(pageArticleList.size());
}
// 如果循环结束了进度还没有完成,则取消进度(不取消会导致页面一直在请求进度信息)
if( !progress.isCompleted() ) {
progress.add(8888888); // 通过设置一个大数(远大于总数)来使进度完成
}
}
/**
* 生成单个文章发布文件
* @param article
* @param publishPath
* @param wordsFilter
* @return
*/
public static String publishOneArticle(Article article, String publishPath, WordsFilter wordsFilter) {
// 删除已发布的文章,如果有的话
String pubUrl = article.getPubUrl();
if(pubUrl != null) {
new File(pubUrl).delete();
}
// 生成发布路径
File publishDir = new File(publishPath);
if (!publishDir.exists())
publishDir.mkdirs();
Document doc = DocumentHelper.createDocument();
doc.setXMLEncoding(ArticleHelper.getSystemEncoding()); //一般:windows “GBK” linux “UTF-8”
Element articleNode = doc.addElement("Article");
Map<String, Object> articleAttributes = article.getAttributesForXForm(); //包含文章的所有属性,包括动态属性
articleAttributes.remove("content");
String className = article.getPublishArticleClassName();
PublishArticleFactory.getInstance(className).publishArticle(articleNode, articleAttributes);
Element eleCnt = articleNode.addElement("content");
eleCnt.addCDATA(filterArticleContent(article.getContent(), wordsFilter)); // 过滤非法信息
// 发布文章对文章附件的处理
Element eleAtts = articleNode.addElement("Attachments");
ArticleHelper.addPicListInfo(eleAtts, article.getAttachments().values());
// 以 “栏目ID_文章ID.xml” 格式命名文章发布的xml文件
String fileName = article.getChannelId() + "_" + article.getId() + ".xml";
String filePathAndName = publishPath + "/" + fileName;
FileHelper.writeXMLDoc(doc, filePathAndName);
return filePathAndName;
}
/**
* 过滤非法的屏蔽和删除信息
*/
private static String filterArticleContent(String content, WordsFilter wordsFilter) {
if ( EasyUtils.isNullOrEmpty(content) ) return "";
if( wordsFilter == null ) return content;
String dropWords = wordsFilter.getForbidWords();
if ( !EasyUtils.isNullOrEmpty(dropWords) ) {
Pattern dropPattern = Pattern.compile(dropWords.replaceAll(",|,", "|"));
Matcher matcher = dropPattern.matcher(content);
if ( matcher.find() ) {
return "文章正文包含非法的信息,已被屏蔽!";
}
}
String cutWords = wordsFilter.getShieldWords();
if ( !EasyUtils.isNullOrEmpty(cutWords) ) {
String cutExpression = cutWords.replaceAll(",|,", "|");
return content.replaceAll(cutExpression, "****");
}
return content;
}
/**
* 文章发布,用于定时发布(也可用于手动即时发布调用)
* @param channelIds
* @param progress
*/
public void publishArticle4TimerJob(List<Long> channelIds, Progress progress) {
for ( Long channelId : channelIds ) {
int totalRows = channelService.getPublishableArticleCount(channelId);
int totalPageNum = totalRows / PAGE_SIZE ;
if( totalRows % PAGE_SIZE > 0 ) {
totalPageNum = totalPageNum + 1;
}
Long siteId = channelService.getSiteIdByChannelId(channelId);
for (int page = 1; page <= totalPageNum; page++) { // 逐页发布文章
List<?> articleList = channelService.getPagePublishableArticleList(channelId, page, PAGE_SIZE);
channelService.publishArticle(articleList, siteId);
progress.add(articleList.size()); // 更新进度条信息进度条
}
}
}
/**
* 获取可发布的文章总数量,用于进度条计算。
* @param channelIdStr
* @param paramsMap
* @return
*/
public int getPublishableArticleCount4TimerJob(String channelIdStr, Map<String, Object> paramsMap) {
int total = 0;
String[] channelIds = channelIdStr.split(",");
List<Long> channelIdList = new ArrayList<Long>();
for ( String temp : channelIds ) {
Long channelId = new Long(temp);
try { // 判断是否对该栏目有发布权限
checkPublishPermission(channelId);
channelIdList.add(channelId);
total += channelService.getPublishableArticleCount(channelId);
} catch (Exception e) {
// do nothing
}
}
paramsMap.put("channelIds", channelIdList);
return total;
}
}