/**
* Copyright (c)2010-2011 Enterprise Website Content Management System(EWCMS), All rights reserved.
* EWCMS PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
* http://www.ewcms.com
*/
package com.ewcms.core.site.service;
import static com.ewcms.common.lang.EmptyUtil.isNotNull;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.acls.domain.GrantedAuthoritySid;
import org.springframework.security.acls.domain.ObjectIdentityImpl;
import org.springframework.security.acls.domain.PrincipalSid;
import org.springframework.security.acls.model.AccessControlEntry;
import org.springframework.security.acls.model.Acl;
import org.springframework.security.acls.model.NotFoundException;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.security.acls.model.Permission;
import org.springframework.security.acls.model.Sid;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import com.ewcms.core.site.ChannelNode;
import com.ewcms.core.site.dao.ChannelDAO;
import com.ewcms.core.site.dao.TemplateDAO;
import com.ewcms.core.site.dao.TemplateSourceDAO;
import com.ewcms.core.site.model.Channel;
import com.ewcms.core.site.model.Site;
import com.ewcms.core.site.model.Template;
import com.ewcms.core.site.model.TemplateSource;
import com.ewcms.core.site.util.ConvertUtil;
import com.ewcms.publication.PublishException;
import com.ewcms.publication.WebPublishFacable;
import com.ewcms.security.acls.domain.EwcmsPermission;
import com.ewcms.security.acls.service.EwcmsAclServiceable;
import com.ewcms.web.util.EwcmsContextUtil;
/**
* 实现专栏服务
*
* @author 周冬初
* @author wuzhijun
*/
@Service
public class ChannelService implements ChannelServiceable{
@Autowired
private ChannelDAO channelDAO;
@Autowired
private TemplateDAO templateDAO;
@Autowired
private TemplateSourceDAO templateSourceDAO;
@Autowired
private EwcmsAclServiceable aclService;
@Autowired
private WebPublishFacable webPublish;
private Set<Permission> getPermissionsofChannel(Channel channel) {
Assert.notNull(channel, "channel is null");
return aclService.getPermissions(channel);
}
@Override
public Set<Permission> getPermissionsById(int id) {
return getPermissionsofChannel(getChannel(id));
}
@Override
public Acl findAclOfChannel(Channel channel){
ObjectIdentity objectIdentity = new ObjectIdentityImpl(channel);
try{
return aclService.readAclById(objectIdentity);
}catch(NotFoundException e){
return null;
}
}
@Override
public void addOrUpdatePermission(Integer id, String name, Integer mask) {
Channel channel = channelDAO.get(id);
Assert.notNull(channel, "channel is null");
aclService.addOrUpdatePermission(channel, name, mask);
}
@Override
public void removePermission(Integer id, String name) {
Channel channel = channelDAO.get(id);
Assert.notNull(channel, "channel is null");
aclService.removePermission(channel, name);
}
@Override
public void updateInheriting(Integer id, boolean inheriting) {
Channel channel = channelDAO.get(id);
Assert.notNull(channel, "channel is null");
Channel parent = inheriting ? channel.getParent() : null;
aclService.updateInheriting(channel,parent);
}
@Override
public List<ChannelNode> getChannelChildren(Integer id,Boolean publicenable) {
List<ChannelNode> nodes = new ArrayList<ChannelNode>();
List<Channel> channels = channelDAO.getChannelChildren(id);
List<String> autorityNames = (List<String>) EwcmsContextUtil.getAutoritynames();
List<String> groupNames = (List<String>)EwcmsContextUtil.getGroupnames();
UserDetails userDetail = EwcmsContextUtil.getUserDetails();
Boolean permit = false;
for (Channel channel : channels) {
if (publicenable && !channel.getPublicenable()) continue;
permit = false;
if (autorityNames.contains("ROLE_ADMIN")){
permit = true;
}else{
//根据用户组和用户查询显示栏目
permit = getEntriesInheriting(channel, autorityNames, groupNames, userDetail);
}
if (permit){
ChannelNode node = new ChannelNode(channel,getPermissionsofChannel(channel));
nodes.add(node);
}
}
return nodes;
}
private Boolean getEntriesInheriting(Channel channel, List<String> autorityNames, List<String> groupNames, UserDetails userDetail){
Acl acl = findAclOfChannel(channel);
if (acl == null) return false;
if(acl.getEntries() == null || acl.getEntries().isEmpty()) {
Boolean inherit = acl.isEntriesInheriting();
if (!inherit) {
return false;
}else{
Channel parent = channel.getParent();
if (parent == null) return false;
return getEntriesInheriting(parent, autorityNames, groupNames, userDetail);
}
}
List<AccessControlEntry> aces = acl.getEntries();
for(AccessControlEntry ace : aces){
Sid sid = ace.getSid();
String n = (sid instanceof PrincipalSid) ? ((PrincipalSid)sid).getPrincipal() : ((GrantedAuthoritySid)sid).getGrantedAuthority();
if (groupNames.contains(n) || userDetail.getUsername().equals(n)){
return true;
}
}
Boolean inherit = acl.isEntriesInheriting();
if (!inherit) return false;
Channel parent = channel.getParent();
if (parent == null) return false;
return getEntriesInheriting(parent, autorityNames, groupNames, userDetail);
}
/**
* 初始站点专栏访问权限
*
* @param channel 站点专栏
* @param createCommon 创建通用权限(true:创建通用权限)
* @param inherit 继承父站点专栏权限
*/
private void initAclOfChannel(Channel channel,boolean createCommon,boolean inherit){
Sid principalSid = new PrincipalSid(SecurityContextHolder.getContext().getAuthentication());
aclService.addPermission(channel,principalSid,EwcmsPermission.ADMIN);
if(createCommon){
aclService.addPermission(channel,new GrantedAuthoritySid("ROLE_USER"),EwcmsPermission.READ);
aclService.addPermission(channel,new GrantedAuthoritySid("ROLE_WRITER"),EwcmsPermission.WRITE);
aclService.addPermission(channel,new GrantedAuthoritySid("ROLE_EDITOR"),EwcmsPermission.PUBLISH);
}
if(inherit && channel.getParent() != null){
aclService.updateInheriting(channel, channel.getParent());
}
}
@Override
public ChannelNode channelNodeRoot() {
Channel channel = channelDAO.getChannelRoot(getCurSite().getId());
if (channel == null) {
channel = new Channel();
channel.setDir("");
channel.setPubPath("");
channel.setAbsUrl("");
channel.setUrl("");
channel.setName(getCurSite().getSiteName());
channel.setSite(getCurSite());
channelDAO.persist(channel);
initAclOfChannel(channel,true,false);
}
// Sid principalSid = new PrincipalSid(SecurityContextHolder.getContext().getAuthentication());
// aclService.addPermission(channel,principalSid,EwcmsPermission.ADMIN);
//
//
// aclService.addPermission(channel,new GrantedAuthoritySid("ROLE_USER"),EwcmsPermission.READ);
// aclService.addPermission(channel,new GrantedAuthoritySid("ROLE_WRITER"),EwcmsPermission.WRITE);
// aclService.addPermission(channel,new GrantedAuthoritySid("ROLE_EDITOR"),EwcmsPermission.PUBLISH);
return new ChannelNode(channel,getPermissionsofChannel(channel));
}
@Override
public Channel getChannelRoot() {
Channel channel = channelDAO.getChannelRoot(getCurSite().getId());
return channel;
}
@Override
public Integer addChannel(Integer parentId, String name) {
Assert.notNull(parentId, "parentId is null");
Channel channel = new Channel();
channel.setName(name);
channel.setParent(channelDAO.get(parentId));
channel.setSite(getCurSite());
channel.setDir(ConvertUtil.pinYin(name));
channel.setSort(channelDAO.findMaxSiblingChannel(parentId) + 1);
channelDAO.persist(channel);
initAclOfChannel(channel,true,true);
return channel.getId();
}
@Override
public void renameChannel(Integer id, String name) {
Channel vo = getChannel(id);
vo.setName(name);
channelDAO.merge(vo);
}
@Override
public Integer updChannel(Channel channel) {
channelDAO.merge(channel);
updAbsUrlAndPubPath(channel.getId(),getCurSite().getId());
return channel.getId();
}
/**
* 更新子专栏的AbsUrl和PubPath
*
* 专栏的目录和链接地址发生改变,则子站点专栏的absUrl和pubPath也要发生改变。
*
* @param channelId 专栏编号
* @param siteId 站点编号
*/
private void updAbsUrlAndPubPath(int channelId,int siteId) {
Channel channel = channelDAO.get(channelId);
if(channel == null || (int)channel.getSite().getId() != siteId){
return;
}
List<Channel> children = channelDAO.getChannelChildren(channelId);
for (Channel child : children ) {
child.setAbsUrl(null);
child.setPubPath(null);
channelDAO.merge(child);
updAbsUrlAndPubPath(child.getId(),siteId);
}
}
public void delChannel(Integer id) {
channelDAO.removeByPK(id);
}
public Channel getChannel(Integer id) {
return channelDAO.get(id);
}
private Site getCurSite() {
return EwcmsContextUtil.getCurrentSite();
}
@Override
public Channel getChannelRoot(Integer siteId) {
return channelDAO.getChannelRoot(siteId);
}
@Override
public Channel getChannel(Integer siteId, Integer id) {
return this.getChannel(id);
}
@Override
public List<Channel> getChannelChildren(Integer id) {
return channelDAO.getChannelChildren(id);
}
@Override
public Channel getChannelByUrlOrPath(Integer siteId, String path) {
return channelDAO.getChannelByURL(siteId, path);
}
@Override
public void forceRelease(Integer channelId, Boolean children) throws PublishException{
if (isNotNull(channelId)) {
webPublish.publishChannel(channelId, true, children);
}
}
@Override
public void downChannel(Integer channelId, Integer parentId) {
if (channelId != null && parentId != null){
Long maxSort = channelDAO.findMaxSiblingChannel(parentId);
Channel channel = channelDAO.get(channelId);
if (channel.getSort().longValue() != maxSort.longValue()){
Long sort = channel.getSort();
sort = sort + 1;
Channel channel_prev = channelDAO.findChannelByParentIdAndSort(parentId, sort);
channel.setSort(sort);
channel_prev.setSort(sort - 1);
channelDAO.merge(channel);
channelDAO.merge(channel_prev);
}
}
}
@Override
public void upChannel(Integer channelId, Integer parentId) {
if (channelId != null && parentId != null){
Channel channel = channelDAO.get(channelId);
if (channel.getSort().longValue() > 1){
Long sort = channel.getSort();
sort = sort - 1;
Channel channel_prev = channelDAO.findChannelByParentIdAndSort(parentId, sort);
channel.setSort(sort);
channel_prev.setSort(sort + 1);
channelDAO.merge(channel);
channelDAO.merge(channel_prev);
}
}
}
public void moveSortChannel(Integer channelId, Integer parentId, Long sort){
if (channelId != null && parentId != null){
Channel moveChannel = channelDAO.get(channelId);
Long oldSort = moveChannel.getSort();
if (sort.longValue() == oldSort.longValue()) return;
moveChannel.setSort(sort);
if (sort.longValue() > oldSort.longValue()){
List<Channel> channels = channelDAO.findChannelByParentIdAndLtSort(channelId, parentId, sort, oldSort);
if (channels == null || channels.isEmpty()) return;
for (Channel channel : channels){
sort--;
channel.setSort(sort);
channelDAO.merge(channel);
}
}else{
List<Channel> channels = channelDAO.findChannelByParentIdAndGtSort(channelId, parentId, sort, oldSort);
if (channels == null || channels.isEmpty()) return;
for (Channel channel : channels){
sort++;
channel.setSort(sort);
channelDAO.merge(channel);
}
}
channelDAO.merge(moveChannel);
}
}
@Override
public void moveToChannel(Integer channelId, Integer parentId) {
Channel moveChannel = channelDAO.get(channelId);
Long sort = moveChannel.getSort();
Integer moveParentId = moveChannel.getParent().getId();
Channel targetParentChannel = channelDAO.get(parentId);
Long maxSort = channelDAO.findMaxSiblingChannel(parentId);
moveChannel.setParent(targetParentChannel);
moveChannel.setSort(maxSort + 1);
List<Channel> channels = channelDAO.findChannelByGreaterThanSort(moveParentId, sort);
if (channels != null && !channels.isEmpty()){
for (Channel channel : channels){
channel.setSort(channel.getSort() - 1);
channelDAO.merge(channel);
}
}
updChannel(moveChannel);
}
@Override
public void exportChannelZip(Integer channelId, ZipOutputStream zos, String channelPath){
try{
Channel channel = getChannel(channelId);
if (channel == null) return;
//创建栏目目录
String filePath = channelPath + channel.getName() + "/";
ZipEntry zipEntry = new ZipEntry(filePath);
zipEntry.setUnixMode(755);
zos.putNextEntry(zipEntry);
//创建栏目目录下一级的“模板”目录
String templatePath = filePath + "模板/";
zipEntry = new ZipEntry(templatePath);
zipEntry.setUnixMode(755);
zos.putNextEntry(zipEntry);
//创建栏目目录下一级的“资源”目录
String templateSourcePath = filePath + "资源/";
zipEntry = new ZipEntry(templateSourcePath);
zipEntry.setUnixMode(755);
zos.putNextEntry(zipEntry);
List<Template> templates = templateDAO.getTemplatesInChannel(channelId);
List<TemplateSource> templateSources = templateSourceDAO.getTemplateSourceInChannel(channelId);
for (Template template : templates){
if (template == null || template.getTemplateEntity() == null) continue;
String fileName = template.getName();
zipEntry = new ZipEntry(templatePath + fileName);
zipEntry.setUnixMode(644);
zos.putNextEntry(zipEntry);
BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(template.getTemplateEntity().getTplEntity()));
int b;
while((b = bis.read())!=-1){
zos.write(b);
}
zos.closeEntry();
bis.close();
}
for (TemplateSource templateSource : templateSources){
if (templateSource == null || templateSource.getSourceEntity() == null) continue;
String fileName = templateSource.getName();
zipEntry = new ZipEntry(templateSourcePath + fileName);
zipEntry.setUnixMode(644);
zos.putNextEntry(zipEntry);
BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(templateSource.getSourceEntity().getSrcEntity()));
int b;
while((b = bis.read())!=-1){
zos.write(b);
}
zos.closeEntry();
bis.close();
}
List<Channel> childrenChannels = getChannelChildren(channelId);
if (childrenChannels != null){
for (Channel childrenChannel : childrenChannels){
exportChannelZip(childrenChannel.getId(), zos, filePath);
}
}
}catch(Exception e){
}
}
@Override
public List<Integer> findAppChannel(Integer channelId){
List<Integer> channelIds = new ArrayList<Integer>();
Channel channel = channelDAO.get(channelId);
String appChannel = channel.getAppChannel();
if (appChannel != null && appChannel.length() > 0){
String[] appChannelIds = appChannel.split(",");
for (String appChannelId : appChannelIds){
try{
Channel vo = channelDAO.get(Integer.valueOf(appChannelId));
if (vo != null && vo.getId() != null) {
channelIds.add(vo.getId());
}
}catch(Exception e){
}
}
}
return channelIds;
}
@Override
public void delAppChannel(Integer channelId, Integer appChannelId){
List<Integer> appChannelIds = findAppChannel(channelId);
if (!appChannelIds.isEmpty()){
appChannelIds.remove(appChannelId);
Channel channel = channelDAO.get(channelId);
if (appChannelIds.isEmpty()){
channel.setAppChannel(null);
}else{
StringBuffer sb = new StringBuffer();
int appChannelIdSize = appChannelIds.size();
for (int i = 0; i < appChannelIdSize - 1; i++){
if (channelId.intValue() == appChannelIds.get(i).intValue()) continue;
sb.append(appChannelIds.get(i) + ",");
}
sb.append(appChannelIds.get(appChannelIdSize - 1));
channel.setAppChannel(sb.toString());
}
channelDAO.merge(channel);
}
}
@Override
public Channel getChannelParent(Integer id) {
Channel channel = channelDAO.get(id);
if (channel != null && channel.getParent() != null) return channel.getParent();
return null;
}
}