. Generic "command servlet" implementation

- Replaces specific command servlets, such as the WorkflowActionServlet with a generic CommandServlet

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2618 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Kevin Roast
2006-04-04 13:18:11 +00:00
parent f4a53302aa
commit 54c9595dc6
10 changed files with 657 additions and 413 deletions

View File

@@ -0,0 +1,59 @@
/*
* 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.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.web.bean.WorkflowUtil;
/**
* Approve Workflow command implementation
*
* @author Kevin Roast
*/
public final class ApproveWorkflowCommand implements Command
{
public static final String PROP_TARGET = "target";
private static final String[] PROPERTIES = new String[] {PROP_TARGET};
/**
* @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 void execute(ServiceRegistry serviceRegistry, Map<String, Object> properties)
{
// get the target Node for the command
NodeRef nodeRef = (NodeRef)properties.get(PROP_TARGET);
if (nodeRef == null)
{
throw new IllegalArgumentException(
"Unable to execute ApproveCommand - mandatory parameter not supplied: " + PROP_TARGET);
}
WorkflowUtil.approve(nodeRef, serviceRegistry.getNodeService(), serviceRegistry.getCopyService());
}
}

View File

@@ -0,0 +1,59 @@
/*
* 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 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;
/**
* Initial implementation of a Command Processor that is always passed enough URL elements
* to construct a single NodeRef argument. The NodeRef is checked against READ permissions
* for the current user during the validateArguments() call.
* <p>
* This class should be enough to form the base of Command Processor objects that only require
* a single NodeRef passed on the URL.
*
* @author Kevin Roast
*/
public abstract class BaseNodeCommandProcessor implements CommandProcessor
{
protected NodeRef targetRef;
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#validateArguments(org.alfresco.service.ServiceRegistry, java.lang.String[])
*/
public boolean validateArguments(ServiceRegistry serviceRegistry, String[] args)
{
if (args.length < 3)
{
throw new IllegalArgumentException("Not enough URL arguments passed to command servlet.");
}
// get NodeRef to the node with the workflow attached to it
StoreRef storeRef = new StoreRef(args[0], args[1]);
this.targetRef = new NodeRef(storeRef, args[2]);
// get the services we need to execute the workflow command
PermissionService permissionService = serviceRegistry.getPermissionService();
// check that the user has at least READ access on the node - else redirect to the login page
return (permissionService.hasPermission(this.targetRef, PermissionService.READ) == AccessStatus.ALLOWED);
}
}

View File

@@ -0,0 +1,42 @@
/*
* 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.service.ServiceRegistry;
/**
* Simple servlet command pattern interface.
*
* @author Kevin Roast
*/
public interface Command
{
/**
* Execute the command
*
* @param serviceRegistry The ServiceRegistry instance
* @param properties Bag of named properties for the command
*/
public void execute(ServiceRegistry serviceRegistry, Map<String, Object> properties);
/**
* @return the names of the properties required for this command
*/
public String[] getPropertyNames();
}

View File

@@ -0,0 +1,97 @@
/*
* 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.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Command Factory helper
*
* @author Kevin Roast
*/
public final class CommandFactory
{
private static Log logger = LogFactory.getLog(CommandFactory.class);
private static CommandFactory instance = new CommandFactory();
private static Map<String, Class> registry = new HashMap<String, Class>(16, 1.0f);
/**
* Private constructor - protect the singleton instance
*/
private CommandFactory()
{
}
/**
* @return the singleton CommandFactory instance
*/
public static CommandFactory getInstance()
{
return instance;
}
/**
* Register a command name against an implementation
*
* @param name Unique name of the command
* @param clazz Class implementation of the command
*/
public void registerCommand(String name, Class clazz)
{
registry.put(name, clazz);
}
/**
* Create a command instance of the specified command name
*
* @param name Name of the command to create (must be registered)
*
* @return the Command instance or null if not found
*/
public Command createCommand(String name)
{
Command result = null;
// lookup command by name in the registry
Class clazz = registry.get(name);
if (clazz != null)
{
try
{
Object obj = clazz.newInstance();
if (obj instanceof Command)
{
result = (Command)obj;
}
}
catch (Throwable err)
{
// return default if this occurs
logger.warn("Unable to create workflow command instance '" + name +
"' with classname '" + clazz.getName() + "' due to error: " + err.getMessage());
}
}
return result;
}
}

View File

@@ -0,0 +1,70 @@
/*
* 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 org.alfresco.service.ServiceRegistry;
/**
* This interfaces defines the contract and lifecycle of a Servlet Command Processor.
* <p>
* A command processor is defined as a class capable of executing a set of related Command
* objects. It performs the bulk of the work for the command servlet. The processor impl
* is responsible for validating that the command can be processed (given the supplied remaining
* URL arguments from the servlet) and processing the command. It is also responsible for
* supply an output status page on successfuly execution of the command.
* <p>
* The arguments passed to a Command Processor are the remaining URL elements from the command
* servlet URL after removing the web-app name, servlet name and command processor name.
*
* @author Kevin Roast
*/
public interface CommandProcessor
{
/**
* Pass and validate URL arguments for the command processor. Validate if the command can be
* executed given the arguments supplied. Generally at this post a Command Processor will
* convert the supplied arguments to the objects it expects, and also check any permissions
* that are required by the current user to execute the command.
*
* @param args String[] of the remaining URL arguments to the command servlet.
*
* @return true if the command can be executed by the current user given the supplied args.
*/
public boolean validateArguments(ServiceRegistry serviceRegistry, String[] args);
/**
* Process the supplied command name. It is the responsibility of the Command Processor
* to lookup the specified command name using the CommandFactory registry. For that reason
* it also has the responsiblity to initially register commands it is responsible for so
* 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 command Name of the command to construct and execute
*/
public void process(ServiceRegistry serviceRegistry, String command);
/**
* Output a simple status message to the supplied PrintWriter.
* It can be assumed that the process() method was successful if this method is called.
*
* @param out PrintWriter
*/
public void outputStatus(PrintWriter out);
}

View File

@@ -0,0 +1,59 @@
/*
* 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.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.web.bean.WorkflowUtil;
/**
* Reject Workflow command implementation
*
* @author Kevin Roast
*/
public final class RejectWorkflowCommand implements Command
{
public static final String PROP_TARGET = "target";
private static final String[] PROPERTIES = new String[] {PROP_TARGET};
/**
* @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 void execute(ServiceRegistry serviceRegistry, Map<String, Object> properties)
{
// get the target Node for the command
NodeRef nodeRef = (NodeRef)properties.get(PROP_TARGET);
if (nodeRef == null)
{
throw new IllegalArgumentException(
"Unable to execute RejectCommand - mandatory parameter not supplied: " + PROP_TARGET);
}
WorkflowUtil.reject(nodeRef, serviceRegistry.getNodeService(), serviceRegistry.getCopyService());
}
}

View File

@@ -0,0 +1,72 @@
/*
* 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 org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.ServiceRegistry;
/**
* Workflow specific command processor implementation.
* <p>
* Responsible for executing 'approve' and 'reject' workflow commands on a Node.
*
* @author Kevin Roast
*/
public final class WorkflowCommandProcessor extends BaseNodeCommandProcessor
{
private String command;
static
{
// add our commands to the command registry
CommandFactory.getInstance().registerCommand("approve", ApproveWorkflowCommand.class);
CommandFactory.getInstance().registerCommand("reject", RejectWorkflowCommand.class);
}
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#process(org.alfresco.service.ServiceRegistry, java.lang.String)
*/
public void process(ServiceRegistry serviceRegistry, String command)
{
Map<String, Object> properties = new HashMap<String, Object>(1, 1.0f);
// all workflow commands use a "target" Node property as an argument
properties.put(ApproveWorkflowCommand.PROP_TARGET, this.targetRef);
Command cmd = CommandFactory.getInstance().createCommand(command);
if (cmd == null)
{
throw new AlfrescoRuntimeException("Unregistered workflow command specified: " + command);
}
cmd.execute(serviceRegistry, properties);
this.command = command;
}
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#outputStatus(java.io.PrintWriter)
*/
public void outputStatus(PrintWriter out)
{
out.print("Workflow command: '");
out.print(this.command);
out.print("' executed against node: ");
out.println(this.targetRef.toString());
}
}