WCMPublicationServiceImpl.java
/*
* Copyright (C) 2003-2008 eXo Platform SAS.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either version 3
* 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, see<http://www.gnu.org/licenses/>.
*/
package org.exoplatform.services.wcm.extensions.publication;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.TreeSet;
import javax.jcr.Node;
import javax.jcr.lock.Lock;
import org.apache.commons.lang.StringUtils;
import org.exoplatform.container.xml.InitParams;
import org.exoplatform.ecm.utils.lock.LockUtil;
import org.exoplatform.ecm.webui.utils.Utils;
import org.exoplatform.services.ecm.publication.PublicationPlugin;
import org.exoplatform.services.ecm.publication.PublicationService;
import org.exoplatform.services.jcr.core.ManageableRepository;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.security.Identity;
import org.exoplatform.services.security.IdentityRegistry;
import org.exoplatform.services.wcm.core.NodeLocation;
import org.exoplatform.services.wcm.core.NodetypeConstant;
import org.exoplatform.services.wcm.extensions.publication.context.impl.ContextConfig.Context;
import org.exoplatform.services.wcm.extensions.publication.impl.PublicationManagerImpl;
import org.exoplatform.services.wcm.extensions.publication.lifecycle.authoring.AuthoringPublicationConstant;
import org.exoplatform.services.wcm.extensions.publication.lifecycle.impl.LifecyclesConfig.Lifecycle;
import org.exoplatform.services.wcm.extensions.publication.lifecycle.impl.LifecyclesConfig.State;
import org.exoplatform.services.wcm.extensions.utils.ContextComparator;
import org.exoplatform.services.wcm.publication.WebpagePublicationPlugin;
import org.exoplatform.services.wcm.utils.WCMCoreUtils;
public class WCMPublicationServiceImpl
extends
org.exoplatform.services.wcm.publication.WCMPublicationServiceImpl {
private static final Log LOG = ExoLogger.getLogger(WCMPublicationServiceImpl.class.getName());
private String publicationLocation = "collaboration:/";
private String[] notAllowChildNodeEnrollInPubliction = new String[] { NodetypeConstant.EXO_WEBCONTENT };
/**
* Instantiates a new WCM publication service. This service delegate to
* PublicationService to manage the publication
*/
public WCMPublicationServiceImpl(InitParams initParams) {
super();
this.publicationService = WCMCoreUtils.getService(PublicationService.class);
if(initParams.getValueParam("publicationLocation") != null) {
publicationLocation = initParams.getValueParam("publicationLocation").getValue();
}
if(initParams.getValueParam("notAllowChildNodeEnrollInPubliction") != null) {
if(initParams.getValueParam("notAllowChildNodeEnrollInPubliction").getValue().indexOf(";") > -1) {
notAllowChildNodeEnrollInPubliction =
initParams.getValueParam("notAllowChildNodeEnrollInPubliction").getValue().split(";");
}
}
}
/**
* This default implementation uses "States and versions based publication" as
* a default lifecycle for all sites and "Simple Publishing" for the root
* user.
*/
public void enrollNodeInLifecycle(Node node, String siteName, String remoteUser) {
try {
if (LOG.isInfoEnabled()) LOG.info(node.getPath() + "::" + siteName + "::"+remoteUser);
PublicationManagerImpl publicationManagerImpl = WCMCoreUtils.getService(PublicationManagerImpl.class);
ContextComparator comparator = new ContextComparator();
TreeSet<Context> treeSetContext = new TreeSet<Context>(comparator);
treeSetContext.addAll(publicationManagerImpl.getContexts());
for (Context context : treeSetContext) {
boolean pathVerified = true;
boolean nodetypeVerified = true;
boolean siteVerified = true;
boolean membershipVerified = true;
String path = context.getPath();
String nodetype = context.getNodetype();
String site = context.getSite();
List<String> memberships = new ArrayList<String>();
if (context.getMembership() != null) {
memberships.add(context.getMembership());
}
if (context.getMemberships() != null) {
memberships.addAll(context.getMemberships());
}
if (path != null) {
String workspace = node.getSession().getWorkspace().getName();
ManageableRepository manaRepository = (ManageableRepository) node.getSession()
.getRepository();
String repository = manaRepository.getConfiguration().getName();
String[] pathTab = path.split(":");
pathVerified = node.getPath().contains(pathTab[2]) && (repository.equals(pathTab[0]))
&& (workspace.equals(pathTab[1]));
}
if (nodetype != null)
nodetypeVerified = nodetype.equals(node.getPrimaryNodeType().getName());
if (site != null)
siteVerified = site.equals(siteName);
if (memberships.size() > 0) {
for (String membership : memberships) {
String[] membershipTab = membership.split(":");
IdentityRegistry identityRegistry = WCMCoreUtils.getService(IdentityRegistry.class);
Identity identity = identityRegistry.getIdentity(remoteUser);
membershipVerified = identity.isMemberOf(membershipTab[1], membershipTab[0]);
if (membershipVerified)
break;
}
}
if (pathVerified && nodetypeVerified && siteVerified && membershipVerified) {
Lifecycle lifecycle = publicationManagerImpl.getLifecycle(context.getLifecycle());
String lifecycleName = this.getWebpagePublicationPlugins()
.get(lifecycle.getPublicationPlugin())
.getLifecycleName();
if (node.canAddMixin("publication:authoring")) {
node.addMixin("publication:authoring");
node.setProperty("publication:lastUser", remoteUser);
node.setProperty("publication:lifecycle", lifecycle.getName());
}
enrollNodeInLifecycle(node, lifecycleName);
setInitialState(node, lifecycle, remoteUser);
break;
}
}
} catch (Exception ex) {
if (LOG.isErrorEnabled()) {
LOG.error("Couldn't complete the enrollement : ", ex);
}
}
}
/**
* Automatically move to initial state if 'automatic'
*
* @param node
* @param lifecycle
* @throws Exception
*/
private void setInitialState(Node node, Lifecycle lifecycle, String remoteUser) throws Exception {
List<State> states = lifecycle.getStates();
if (states == null || states.size() <= 0) {
if (LOG.isWarnEnabled()) {
LOG.warn("could not find an initial state in lifecycle " + lifecycle.getName());
}
} else {
String initialState = states.get(0).getState();
PublicationPlugin publicationPlugin = publicationService.getPublicationPlugins()
.get(AuthoringPublicationConstant.LIFECYCLE_NAME);
HashMap<String, String> context = new HashMap<String, String>();
NodeLocation currentRevisionLocation = NodeLocation.getNodeLocationByNode(node);
Node currentRevision = getCurrentRevision(currentRevisionLocation);
if (currentRevision != null) {
context.put(AuthoringPublicationConstant.CURRENT_REVISION_NAME, currentRevision.getName());
}
try {
if (node.isLocked()) {
Lock lock = node.getLock();
String owner = lock.getLockOwner();
if (LOG.isInfoEnabled())
LOG.info("node is locked by owner, unlocking it for enrollement");
if (node.holdsLock() && remoteUser.equals(owner)) {
String lockToken = LockUtil.getLockToken(node);
if (lockToken != null) {
node.getSession().addLockToken(lockToken);
}
node.unlock();
node.removeMixin(Utils.MIX_LOCKABLE);
// remove lock from Cache
LockUtil.removeLock(node);
}
}
context.put(AuthoringPublicationConstant.IS_INITIAL_PHASE, "true");
node.setProperty("publication:lastUser", remoteUser);
publicationPlugin.changeState(node, initialState, context);
} catch (Exception e) {
if (LOG.isErrorEnabled()) {
LOG.error("Error setting staged state : ", e);
}
}
}
}
public Node getCurrentRevision(NodeLocation currentRevisionLocation) {
return NodeLocation.getNodeByLocation(currentRevisionLocation);
}
/**
* This default implementation checks if the state is valid then delegates the
* update to the node WebpagePublicationPlugin.
*/
public void updateLifecyleOnChangeContent(Node node,
String siteName,
String remoteUser,
String newState) throws Exception {
if(!node.getPath().startsWith(publicationLocation.split(":")[1])
&& !publicationService.isNodeEnrolledInLifecycle(node)) return;
if(node.getPrimaryNodeType().getName().equals(NodetypeConstant.NT_FILE)) {
for(String nodeType : notAllowChildNodeEnrollInPubliction) {
if(!allowEnrollInPublication(node, nodeType)) return;
}
}
if (!publicationService.isNodeEnrolledInLifecycle(node)) {
enrollNodeInLifecycle(node, siteName, remoteUser);
}
String lifecycleName = publicationService.getNodeLifecycleName(node);
WebpagePublicationPlugin publicationPlugin = this.getWebpagePublicationPlugins()
.get(lifecycleName);
publicationPlugin.updateLifecyleOnChangeContent(node, remoteUser, newState);
listenerService.broadcast(UPDATE_EVENT, cmsService, node);
}
private boolean allowEnrollInPublication(Node node, String nodeType) throws Exception {
String path = node.getPath();
Node parentNode = node.getParent();
while(!path.equals("/") && path.length() > 0) {
parentNode = (Node)node.getSession().getItem(path);
if(parentNode.isNodeType(nodeType)) return false;
path = path.substring(0, path.lastIndexOf("/"));
}
return true;
}
}