From ac24ab93732e8befc4c6c93145c4b1eec6874a68 Mon Sep 17 00:00:00 2001 From: Kevin Roast Date: Fri, 5 May 2006 12:09:15 +0000 Subject: [PATCH] . Rhino JavaScript integration: - APIs for testing of Permissions and checking that an Aspect exists on a node . Added new command processor to config for Command Servlet - new command processor to allow execution of Alfresco JavaScript files via URLs - Wiki docs: http://wiki.alfresco.com/wiki/URL_Addressability#Script_Command_Processor . Fixed issue where a deleted/missing NodeRef on the end of a Link object would cause errors in the web-client - Still needs cleanup/change to assoc mechanism as per AWC-647 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2774 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/web-client-config.xml | 1 + .../web/app/servlet/CommandServlet.java | 2 +- .../command/ApproveWorkflowCommand.java | 4 +- .../web/app/servlet/command/Command.java | 4 +- .../app/servlet/command/CommandProcessor.java | 7 +- .../servlet/command/ExecuteScriptCommand.java | 87 ++++++++++++++ .../command/RejectWorkflowCommand.java | 4 +- .../command/ScriptCommandProcessor.java | 107 ++++++++++++++++++ .../command/WorkflowCommandProcessor.java | 4 +- .../org/alfresco/web/bean/BrowseBean.java | 44 ++++++- .../web/bean/DocumentDetailsBean.java | 5 +- .../alfresco/web/bean/SpaceDetailsBean.java | 5 +- 12 files changed, 259 insertions(+), 15 deletions(-) create mode 100644 source/java/org/alfresco/web/app/servlet/command/ExecuteScriptCommand.java create mode 100644 source/java/org/alfresco/web/app/servlet/command/ScriptCommandProcessor.java diff --git a/config/alfresco/web-client-config.xml b/config/alfresco/web-client-config.xml index f9fef1e0c0..74e331a089 100644 --- a/config/alfresco/web-client-config.xml +++ b/config/alfresco/web-client-config.xml @@ -140,6 +140,7 @@ + diff --git a/source/java/org/alfresco/web/app/servlet/CommandServlet.java b/source/java/org/alfresco/web/app/servlet/CommandServlet.java index 1260a4971e..3b49327adc 100644 --- a/source/java/org/alfresco/web/app/servlet/CommandServlet.java +++ b/source/java/org/alfresco/web/app/servlet/CommandServlet.java @@ -127,7 +127,7 @@ public class CommandServlet extends BaseServlet txn.begin(); // inform the processor to execute the specified command - processor.process(serviceRegistry, command); + processor.process(serviceRegistry, req.getSession(), command); // commit the transaction txn.commit(); diff --git a/source/java/org/alfresco/web/app/servlet/command/ApproveWorkflowCommand.java b/source/java/org/alfresco/web/app/servlet/command/ApproveWorkflowCommand.java index 85a65cb9e0..135da7aadf 100644 --- a/source/java/org/alfresco/web/app/servlet/command/ApproveWorkflowCommand.java +++ b/source/java/org/alfresco/web/app/servlet/command/ApproveWorkflowCommand.java @@ -44,7 +44,7 @@ public final class ApproveWorkflowCommand implements Command /** * @see org.alfresco.web.app.servlet.command.Command#execute(org.alfresco.service.ServiceRegistry, java.util.Map) */ - public void execute(ServiceRegistry serviceRegistry, Map properties) + public Object execute(ServiceRegistry serviceRegistry, Map properties) { // get the target Node for the command NodeRef nodeRef = (NodeRef)properties.get(PROP_TARGET); @@ -55,5 +55,7 @@ public final class ApproveWorkflowCommand implements Command } WorkflowUtil.approve(nodeRef, serviceRegistry.getNodeService(), serviceRegistry.getCopyService()); + + return true; } } diff --git a/source/java/org/alfresco/web/app/servlet/command/Command.java b/source/java/org/alfresco/web/app/servlet/command/Command.java index 1be65fb732..8c55221144 100644 --- a/source/java/org/alfresco/web/app/servlet/command/Command.java +++ b/source/java/org/alfresco/web/app/servlet/command/Command.java @@ -32,8 +32,10 @@ public interface Command * * @param serviceRegistry The ServiceRegistry instance * @param properties Bag of named properties for the command + * + * @return return value from the command if any */ - public void execute(ServiceRegistry serviceRegistry, Map properties); + public Object execute(ServiceRegistry serviceRegistry, Map properties); /** * @return the names of the properties required for this command diff --git a/source/java/org/alfresco/web/app/servlet/command/CommandProcessor.java b/source/java/org/alfresco/web/app/servlet/command/CommandProcessor.java index 54747eabde..1a68c69eab 100644 --- a/source/java/org/alfresco/web/app/servlet/command/CommandProcessor.java +++ b/source/java/org/alfresco/web/app/servlet/command/CommandProcessor.java @@ -18,6 +18,8 @@ package org.alfresco.web.app.servlet.command; import java.io.PrintWriter; +import javax.servlet.http.HttpSession; + import org.alfresco.service.ServiceRegistry; /** @@ -57,10 +59,11 @@ public interface CommandProcessor * they can be constructed later. If the supplied command is unknown to it then an * exception should be thrown to indicate this. * - * @param serviceRegistry serviceRegistry + * @param serviceRegistry ServiceRegistry + * @param session HttpSession * @param command Name of the command to construct and execute */ - public void process(ServiceRegistry serviceRegistry, String command); + public void process(ServiceRegistry serviceRegistry, HttpSession session, String command); /** * Output a simple status message to the supplied PrintWriter. diff --git a/source/java/org/alfresco/web/app/servlet/command/ExecuteScriptCommand.java b/source/java/org/alfresco/web/app/servlet/command/ExecuteScriptCommand.java new file mode 100644 index 0000000000..a005f4d0d1 --- /dev/null +++ b/source/java/org/alfresco/web/app/servlet/command/ExecuteScriptCommand.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ +package org.alfresco.web.app.servlet.command; + +import java.util.Map; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.jscript.RhinoScriptService; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.web.app.Application; +import org.alfresco.web.bean.repository.Repository; + +/** + * Execute Script command implementation + * + * @author Kevin Roast + */ +public final class ExecuteScriptCommand implements Command +{ + public static final String PROP_SCRIPT = "script"; + public static final String PROP_DOCUMENT = "document"; + public static final String PROP_USERPERSON = "person"; + + private static final String[] PROPERTIES = new String[] {PROP_SCRIPT, PROP_DOCUMENT, PROP_USERPERSON}; + + + /** + * @see org.alfresco.web.app.servlet.command.Command#getPropertyNames() + */ + public String[] getPropertyNames() + { + return PROPERTIES; + } + + /** + * @see org.alfresco.web.app.servlet.command.Command#execute(org.alfresco.service.ServiceRegistry, java.util.Map) + */ + public Object execute(ServiceRegistry serviceRegistry, Map properties) + { + // get the target Script node for the command + NodeRef scriptRef = (NodeRef)properties.get(PROP_SCRIPT); + if (scriptRef == null) + { + throw new IllegalArgumentException( + "Unable to execute ExecuteScriptCommand - mandatory parameter not supplied: " + PROP_SCRIPT); + } + + NodeRef personRef = (NodeRef)properties.get(PROP_USERPERSON); + if (personRef == null) + { + throw new IllegalArgumentException( + "Unable to execute ExecuteScriptCommand - mandatory parameter not supplied: " + PROP_USERPERSON); + } + + // get the optional document context ref + NodeRef docRef = (NodeRef)properties.get(PROP_DOCUMENT); + + // build the model needed to execute the script + NodeService nodeService = serviceRegistry.getNodeService(); + Map model = RhinoScriptService.buildDefaultModel( + serviceRegistry, + personRef, + new NodeRef(Repository.getStoreRef(), Application.getCompanyRootId()), + (NodeRef)nodeService.getProperty(personRef, ContentModel.PROP_HOMEFOLDER), + docRef, + nodeService.getPrimaryParent(docRef).getParentRef()); + + // execute the script and return the result + return serviceRegistry.getScriptService().executeScript(scriptRef, null, model); + } +} diff --git a/source/java/org/alfresco/web/app/servlet/command/RejectWorkflowCommand.java b/source/java/org/alfresco/web/app/servlet/command/RejectWorkflowCommand.java index 7d7fb99649..aee30ccb9b 100644 --- a/source/java/org/alfresco/web/app/servlet/command/RejectWorkflowCommand.java +++ b/source/java/org/alfresco/web/app/servlet/command/RejectWorkflowCommand.java @@ -44,7 +44,7 @@ public final class RejectWorkflowCommand implements Command /** * @see org.alfresco.web.app.servlet.command.Command#execute(org.alfresco.service.ServiceRegistry, java.util.Map) */ - public void execute(ServiceRegistry serviceRegistry, Map properties) + public Object execute(ServiceRegistry serviceRegistry, Map properties) { // get the target Node for the command NodeRef nodeRef = (NodeRef)properties.get(PROP_TARGET); @@ -55,5 +55,7 @@ public final class RejectWorkflowCommand implements Command } WorkflowUtil.reject(nodeRef, serviceRegistry.getNodeService(), serviceRegistry.getCopyService()); + + return true; } } diff --git a/source/java/org/alfresco/web/app/servlet/command/ScriptCommandProcessor.java b/source/java/org/alfresco/web/app/servlet/command/ScriptCommandProcessor.java new file mode 100644 index 0000000000..fe3fbc0519 --- /dev/null +++ b/source/java/org/alfresco/web/app/servlet/command/ScriptCommandProcessor.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ +package org.alfresco.web.app.servlet.command; + +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpSession; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.web.app.Application; +import org.alfresco.web.bean.repository.User; + +/** + * @author Kevin Roast + */ +public final class ScriptCommandProcessor implements CommandProcessor +{ + private NodeRef scriptRef; + private NodeRef docRef; + private Object result; + + static + { + // add our commands to the command registry + CommandFactory.getInstance().registerCommand("execute", ExecuteScriptCommand.class); + } + + /** + * @see org.alfresco.web.app.servlet.command.CommandProcessor#validateArguments(org.alfresco.service.ServiceRegistry, java.lang.String, java.lang.String[]) + */ + public boolean validateArguments(ServiceRegistry serviceRegistry, String command, String[] args) + { + if (args.length < 3) + { + throw new IllegalArgumentException("Not enough URL arguments passed to command servlet."); + } + + // get NodeRef to the node script to execute + StoreRef storeRef = new StoreRef(args[0], args[1]); + this.scriptRef = new NodeRef(storeRef, args[2]); + + if (args.length >= 6) + { + storeRef = new StoreRef(args[3], args[4]); + this.docRef = new NodeRef(storeRef, args[5]); + } + + // check we can access the nodes specified + PermissionService ps = serviceRegistry.getPermissionService(); + boolean allowed = (ps.hasPermission(this.scriptRef, PermissionService.READ) == AccessStatus.ALLOWED); + if (this.docRef != null) + { + allowed &= (ps.hasPermission(this.docRef, PermissionService.READ) == AccessStatus.ALLOWED); + } + + // check that the user has at least READ access on the node - else redirect to the login page + return allowed; + } + + /** + * @see org.alfresco.web.app.servlet.command.CommandProcessor#process(org.alfresco.service.ServiceRegistry, java.lang.String) + */ + public void process(ServiceRegistry serviceRegistry, HttpSession session, String command) + { + Map properties = new HashMap(2, 1.0f); + properties.put(ExecuteScriptCommand.PROP_SCRIPT, this.scriptRef); + properties.put(ExecuteScriptCommand.PROP_DOCUMENT, this.docRef); + User user = Application.getCurrentUser(session); + properties.put(ExecuteScriptCommand.PROP_USERPERSON, user.getPerson()); + + Command cmd = CommandFactory.getInstance().createCommand(command); + if (cmd == null) + { + throw new AlfrescoRuntimeException("Unregistered script command specified: " + command); + } + this.result = cmd.execute(serviceRegistry, properties); + } + + /** + * @see org.alfresco.web.app.servlet.command.CommandProcessor#outputStatus(java.io.PrintWriter) + */ + public void outputStatus(PrintWriter out) + { + out.write(this.result != null ? this.result.toString() : "Successfully executed script."); + } +} diff --git a/source/java/org/alfresco/web/app/servlet/command/WorkflowCommandProcessor.java b/source/java/org/alfresco/web/app/servlet/command/WorkflowCommandProcessor.java index 9ddc3e0f5d..05bf786b6a 100644 --- a/source/java/org/alfresco/web/app/servlet/command/WorkflowCommandProcessor.java +++ b/source/java/org/alfresco/web/app/servlet/command/WorkflowCommandProcessor.java @@ -20,6 +20,8 @@ import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; +import javax.servlet.http.HttpSession; + import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.service.ServiceRegistry; @@ -44,7 +46,7 @@ public final class WorkflowCommandProcessor extends BaseNodeCommandProcessor /** * @see org.alfresco.web.app.servlet.command.CommandProcessor#process(org.alfresco.service.ServiceRegistry, java.lang.String) */ - public void process(ServiceRegistry serviceRegistry, String command) + public void process(ServiceRegistry serviceRegistry, HttpSession session, String command) { Map properties = new HashMap(1, 1.0f); // all workflow commands use a "target" Node property as an argument diff --git a/source/java/org/alfresco/web/bean/BrowseBean.java b/source/java/org/alfresco/web/bean/BrowseBean.java index 3547317fcc..2a0e5ae3bc 100644 --- a/source/java/org/alfresco/web/bean/BrowseBean.java +++ b/source/java/org/alfresco/web/bean/BrowseBean.java @@ -862,30 +862,62 @@ public class BrowseBean implements IContextListener public NodePropertyResolver resolverLinkDownload = new NodePropertyResolver() { public Object get(Node node) { NodeRef destRef = (NodeRef)node.getProperties().get(ContentModel.PROP_LINK_DESTINATION); - String destName = Repository.getNameForNode(nodeService, destRef); - return DownloadContentServlet.generateDownloadURL(node.getNodeRef(), destName); + if (nodeService.exists(destRef) == true) + { + String destName = Repository.getNameForNode(nodeService, destRef); + return DownloadContentServlet.generateDownloadURL(node.getNodeRef(), destName); + } + else + { + // TODO: link object is missing - navigate to a page with appropriate message + return "#"; + } } }; public NodePropertyResolver resolverLinkUrl = new NodePropertyResolver() { public Object get(Node node) { NodeRef destRef = (NodeRef)node.getProperties().get(ContentModel.PROP_LINK_DESTINATION); - String destName = Repository.getNameForNode(nodeService, destRef); - return DownloadContentServlet.generateBrowserURL(destRef, destName); + if (nodeService.exists(destRef) == true) + { + String destName = Repository.getNameForNode(nodeService, destRef); + return DownloadContentServlet.generateBrowserURL(destRef, destName); + } + else + { + // TODO: link object is missing - navigate to a page with appropriate message + return "#"; + } } }; public NodePropertyResolver resolverLinkWebdavUrl = new NodePropertyResolver() { public Object get(Node node) { NodeRef destRef = (NodeRef)node.getProperties().get(ContentModel.PROP_LINK_DESTINATION); - return Utils.generateURL(FacesContext.getCurrentInstance(), new Node(destRef), URLMode.WEBDAV); + if (nodeService.exists(destRef) == true) + { + return Utils.generateURL(FacesContext.getCurrentInstance(), new Node(destRef), URLMode.WEBDAV); + } + else + { + // TODO: link object is missing - navigate to a page with appropriate message + return "#"; + } } }; public NodePropertyResolver resolverLinkCifsPath = new NodePropertyResolver() { public Object get(Node node) { NodeRef destRef = (NodeRef)node.getProperties().get(ContentModel.PROP_LINK_DESTINATION); - return Utils.generateURL(FacesContext.getCurrentInstance(), new Node(destRef), URLMode.CIFS); + if (nodeService.exists(destRef) == true) + { + return Utils.generateURL(FacesContext.getCurrentInstance(), new Node(destRef), URLMode.CIFS); + } + else + { + // TODO: link object is missing - navigate to a page with appropriate message + return "#"; + } } }; diff --git a/source/java/org/alfresco/web/bean/DocumentDetailsBean.java b/source/java/org/alfresco/web/bean/DocumentDetailsBean.java index 09f9e7f039..ca259212fd 100644 --- a/source/java/org/alfresco/web/bean/DocumentDetailsBean.java +++ b/source/java/org/alfresco/web/bean/DocumentDetailsBean.java @@ -158,7 +158,10 @@ public class DocumentDetailsBean extends BaseDetailsBean if (ContentModel.TYPE_FILELINK.equals(document.getType())) { NodeRef destRef = (NodeRef)document.getProperties().get(ContentModel.PROP_LINK_DESTINATION); - document = new Node(destRef); + if (nodeService.exists(destRef)) + { + document = new Node(destRef); + } } return document; } diff --git a/source/java/org/alfresco/web/bean/SpaceDetailsBean.java b/source/java/org/alfresco/web/bean/SpaceDetailsBean.java index 93e668ff61..ae8d7c67b6 100644 --- a/source/java/org/alfresco/web/bean/SpaceDetailsBean.java +++ b/source/java/org/alfresco/web/bean/SpaceDetailsBean.java @@ -110,7 +110,10 @@ public class SpaceDetailsBean extends BaseDetailsBean if (ContentModel.TYPE_FOLDERLINK.equals(space.getType())) { NodeRef destRef = (NodeRef)space.getProperties().get(ContentModel.PROP_LINK_DESTINATION); - space = new Node(destRef); + if (nodeService.exists(destRef)) + { + space = new Node(destRef); + } } return space; }