/*
* Copyright (C) 2003-2007 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.cms.actions.impl;
import java.util.HashMap;
import java.util.Map;
import javax.jcr.Item;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.observation.Event;
import javax.jcr.observation.EventIterator;
import org.exoplatform.services.cms.actions.ActionServiceContainer;
import org.exoplatform.services.jcr.RepositoryService;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.security.Identity;
import org.exoplatform.services.security.IdentityConstants;
import org.exoplatform.services.security.IdentityRegistry;
import org.exoplatform.services.security.MembershipEntry;
import org.exoplatform.services.wcm.utils.WCMCoreUtils;
public abstract class BaseActionLauncherListener implements ECMEventListener {
protected String actionName_;
protected String repository_ ;
protected String srcWorkspace_;
protected String srcPath_;
protected String executable_;
protected Map actionVariables_;
private static final Log LOG = ExoLogger.getLogger(BaseActionLauncherListener.class.getName());
public BaseActionLauncherListener(String actionName, String executable,
String repository, String srcWorkspace, String srcPath, Map actionVariables)
throws Exception {
actionName_ = actionName;
executable_ = executable;
repository_ = repository ;
srcWorkspace_ = srcWorkspace;
srcPath_ = srcPath;
actionVariables_ = actionVariables;
}
public String getSrcWorkspace() { return srcWorkspace_; }
public String getRepository() { return repository_; }
@SuppressWarnings("unchecked")
public void onEvent(EventIterator events) {
RepositoryService repositoryService =
WCMCoreUtils.getService(RepositoryService.class);
ActionServiceContainer actionServiceContainer =
WCMCoreUtils.getService(ActionServiceContainer.class);
IdentityRegistry identityRegistry = WCMCoreUtils.getService(IdentityRegistry.class);
while (events.hasNext()) {
Event event = events.nextEvent();
Node node = null;
Session jcrSession = null;
try {
jcrSession = repositoryService.getCurrentRepository().getSystemSession(srcWorkspace_);
String repoName = repositoryService.getCurrentRepository().getConfiguration().getName();
node = (Node) jcrSession.getItem(srcPath_);
String userId = event.getUserID();
Node actionNode = actionServiceContainer.getAction(node, actionName_);
this.executable_ = actionNode.hasProperty("exo:script")?actionNode.getProperty("exo:script").getString() : executable_;
Property rolesProp = actionNode.getProperty("exo:roles");
Value[] roles = rolesProp.getValues();
boolean hasPermission = checkExcetuteable(userId, roles, identityRegistry) ;
if (!hasPermission) {
jcrSession.logout();
return;
}
String path = event.getPath();
if (!checkAffectedNodeType(actionNode, jcrSession, path)) {
jcrSession.logout();
return;
}
Map<String, String> variables = new HashMap<String, String>();
variables.put("eventType", event.getType() + "");
variables.put("initiator", userId);
variables.put("actionName", actionName_);
variables.put("nodePath", path);
variables.put("repository", repoName);
variables.put("srcWorkspace", srcWorkspace_);
variables.put("srcPath", srcPath_);
variables.putAll(actionVariables_);
if(event.getType() == Event.NODE_ADDED) {
try {
node = (Node) jcrSession.getItem(path);
} catch (Exception e) {
if (path.contains("exo:actions")) {
Node tempnode = (Node) jcrSession.getItem(path.substring(0, path.indexOf("exo:actions") - 1));
node = tempnode.getNode("exo:actions")
.getNode(path.substring(path.indexOf("exo:actions") + "exo:actions".length() + 1));
}
}
String nodeType = node.getPrimaryNodeType().getName();
variables.put("document-type", nodeType);
triggerAction(userId, variables, repoName);
} else {
triggerAction(userId, variables, repoName);
}
jcrSession.logout();
} catch (Exception e) {
jcrSession.logout();
if (LOG.isErrorEnabled()) {
LOG.error("Unexpected error", e);
}
}
}
}
public abstract void triggerAction(String userId, Map variables, String repository)
throws Exception; {
}
private boolean checkExcetuteable(String userId, Value[] roles,
IdentityRegistry identityRegistry) throws Exception {
if(IdentityConstants.SYSTEM.equalsIgnoreCase(userId)) {
return true;
}
Identity identity;
if (IdentityConstants.ANONIM.equalsIgnoreCase(userId)) {
return true;
}
identity = identityRegistry.getIdentity(userId);
if(identity == null) {
return false ;
}
for (int i = 0; i < roles.length; i++) {
String role = roles[i].getString();
if("*".equalsIgnoreCase(role))
return true ;
MembershipEntry membershipEntry = MembershipEntry.parse(role) ;
if(identity != null && identity.isMemberOf(membershipEntry)) {
return true ;
}
}
return false ;
}
/**
* Check node added/edited (if available) is one of affected node types
* If exo:affectedNodeTypeNames contains value ALL_DOCUMENT_TYPES then
* all document types (base on template service) will be affected
* @param actionNode
* @param session
* @param path
* @return
* @throws Exception
*/
private boolean checkAffectedNodeType(Node actionNode, Session session, String path)
throws Exception {
if (!session.itemExists(path)) return true;
Item item = session.getItem(path);
if (!item.isNode()) return true;
if (!actionNode.hasProperty("exo:affectedNodeTypeNames")) return true;
Value[] nodeTypes = actionNode.getProperty("exo:affectedNodeTypeNames").getValues();
if (nodeTypes.length == 0) return true;
for (Value nodeType : nodeTypes) {
if (((Node) item).isNodeType(nodeType.getString()))
return true;
}
return false;
}
}