/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.xmlworkflow;
import org.dspace.app.util.Util;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Collection;
import org.dspace.core.Context;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Email;
import org.dspace.core.I18nUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.dspace.eperson.Group;
import org.dspace.eperson.factory.EPersonServiceFactory;
import org.dspace.eperson.service.GroupService;
import org.dspace.xmlworkflow.factory.XmlWorkflowFactory;
import org.dspace.xmlworkflow.factory.XmlWorkflowServiceFactory;
import org.dspace.xmlworkflow.state.Workflow;
import org.dspace.xmlworkflow.storedcomponents.CollectionRole;
import org.dspace.xmlworkflow.storedcomponents.service.CollectionRoleService;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.sql.SQLException;
import java.util.*;
import java.io.StringWriter;
import java.io.PrintWriter;
/**
* Utilty methods for the xml workflow
*
* @author Bram De Schouwer (bram.deschouwer at dot com)
* @author Kevin Van de Velde (kevin at atmire dot com)
* @author Ben Bosman (ben at atmire dot com)
* @author Mark Diggory (markd at atmire dot com)
*/
public class WorkflowUtils extends Util{
/** log4j category */
public static Logger log = Logger.getLogger(WorkflowUtils.class);
protected static final CollectionRoleService collectionRoleService = XmlWorkflowServiceFactory.getInstance().getCollectionRoleService();
protected static final GroupService groupService = EPersonServiceFactory.getInstance().getGroupService();
protected static final XmlWorkflowFactory xmlWorkflowFactory = XmlWorkflowServiceFactory.getInstance().getWorkflowFactory();
/**
* Return a string for logging, containing useful information about the
* current request - the URL, the method and parameters.
*
* @param request
* the request object.
* @return a multi-line string containing information about the request.
*/
public static String getRequestLogInfo(HttpServletRequest request)
{
String report;
report = "-- URL Was: " + getOriginalURL(request) + "\n";
report = report + "-- Method: " + request.getMethod() + "\n";
// First write the parameters we had
report = report + "-- Parameters were:\n";
Enumeration e = request.getParameterNames();
while (e.hasMoreElements())
{
String name = (String) e.nextElement();
if (name.equals("login_password"))
{
// We don't want to write a clear text password
// to the log, even if it's wrong!
report = report + "-- " + name + ": *not logged*\n";
}
else
{
report = report + "-- " + name + ": \""
+ request.getParameter(name) + "\"\n";
}
}
return report;
}
/**
* Get the original request URL.
*
* @param request
* the HTTP request
*
* @return the original request URL
*/
public static String getOriginalURL(HttpServletRequest request)
{
// Make sure there's a URL in the attribute
storeOriginalURL(request);
return ((String) request.getAttribute("dspace.original.url"));
}
/**
* Put the original request URL into the request object as an attribute for
* later use. This is necessary because forwarding a request removes this
* information. The attribute is only written if it hasn't been before; thus
* it can be called after a forward safely.
*
* @param request
* Servlet's HTTP request object.
*/
public static void storeOriginalURL(HttpServletRequest request)
{
String orig = (String) request.getAttribute("dspace.original.url");
if (orig == null)
{
String fullURL = request.getRequestURL().toString();
if (request.getQueryString() != null)
{
fullURL = fullURL + "?" + request.getQueryString();
}
request.setAttribute("dspace.original.url", fullURL);
}
}
/**
* Send an alert to the designated "alert recipient" - that is, when a
* database error or internal error occurs, this person is sent an e-mail
* with details.
* <P>
* The recipient is configured via the "alert.recipient" property in
* <code>dspace.cfg</code>. If this property is omitted, no alerts are
* sent.
* <P>
* This method "swallows" any exception that might occur - it will just be
* logged. This is because this method will usually be invoked as part of an
* error handling routine anyway.
*
* @param request
* the HTTP request leading to the error
* @param exception
* the exception causing the error, or null
*/
public static void sendAlert(HttpServletRequest request, Exception exception)
{
String logInfo = WorkflowUtils.getRequestLogInfo(request);
Context c = (Context) request.getAttribute("dspace.context");
try
{
String recipient = ConfigurationManager
.getProperty("alert.recipient");
if (StringUtils.isNotBlank(recipient))
{
Email email = Email.getEmail(I18nUtil.getEmailFilename(c.getCurrentLocale(), "internal_error"));
email.addRecipient(recipient);
email.addArgument(ConfigurationManager
.getProperty("dspace.url"));
email.addArgument(new Date());
email.addArgument(request.getSession().getId());
email.addArgument(logInfo);
String stackTrace;
if (exception != null)
{
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
exception.printStackTrace(pw);
pw.flush();
stackTrace = sw.toString();
}
else
{
stackTrace = "No exception";
}
email.addArgument(stackTrace);
email.send();
}
}
catch (Exception e)
{
// Not much we can do here!
log.warn("Unable to send email alert", e);
}
}
/***************************************
* WORKFLOW ROLE MANAGEMENT
**************************************/
/**
* Creates a role for a collection by linking a group of epersons to a role ID
*
* @param context
* The relevant DSpace Context.
* @param collection
* the target collection
* @param roleId
* the role to be linked.
* @param group
* group of EPersons
* @throws AuthorizeException
* Exception indicating the current user of the context does not have permission
* to perform a particular action.
* @throws SQLException
* An exception that provides information on a database access error or other errors.
*/
public static void createCollectionWorkflowRole(Context context, Collection collection, String roleId, Group group)
throws AuthorizeException, SQLException
{
CollectionRole ass = collectionRoleService.create(context, collection, roleId, group);
collectionRoleService.update(context, ass);
}
/*
* Deletes a role group linked to a given role and a collection
*
* @param context
* The relevant DSpace Context.
* @param collection
*
* @param roleId
*
* @throws SQLException
* An exception that provides information on a database access error or other errors.
* @throws IOException
* A general class of exceptions produced by failed or interrupted I/O operations.
* @throws WorkflowConfigurationException
* occurs if there is a configuration error in the workflow
*/
public static void deleteRoleGroup(Context context, Collection collection, String roleID)
throws SQLException, IOException, WorkflowConfigurationException
{
Workflow workflow = xmlWorkflowFactory.getWorkflow(collection);
Role role = workflow.getRoles().get(roleID);
if (role.getScope() == Role.Scope.COLLECTION) {
CollectionRole ass = collectionRoleService.find(context, collection, roleID);
collectionRoleService.delete(context, ass);
}
}
public static HashMap<String, Role> getCollectionRoles(Collection thisCollection) throws IOException, WorkflowConfigurationException, SQLException {
Workflow workflow = xmlWorkflowFactory.getWorkflow(thisCollection);
LinkedHashMap<String, Role> result = new LinkedHashMap<String, Role>();
if (workflow != null) {
//Make sure we find one
HashMap<String, Role> allRoles = workflow.getRoles();
//We have retrieved all our roles, not get the ones which can be configured by the collection
for (String roleId : allRoles.keySet()) {
Role role = allRoles.get(roleId);
// We just require the roles which have a scope of collection
if (role.getScope() == Role.Scope.COLLECTION && !role.isInternal()) {
result.put(roleId, role);
}
}
}
return result;
}
public static HashMap<String, Role> getCollectionAndRepositoryRoles(Collection thisCollection) throws IOException, WorkflowConfigurationException, SQLException {
Workflow workflow = xmlWorkflowFactory.getWorkflow(thisCollection);
LinkedHashMap<String, Role> result = new LinkedHashMap<String, Role>();
if (workflow != null) {
//Make sure we find one
HashMap<String, Role> allRoles = workflow.getRoles();
//We have retrieved all our roles, not get the ones which can be configured by the collection
for (String roleId : allRoles.keySet()) {
Role role = allRoles.get(roleId);
// We just require the roles which have a scope of collection
if ((role.getScope() == Role.Scope.COLLECTION || role.getScope() == Role.Scope.REPOSITORY) && !role.isInternal()) {
result.put(roleId, role);
}
}
}
return result;
}
public static HashMap<String, Role> getAllExternalRoles(Collection thisCollection) throws IOException, WorkflowConfigurationException, SQLException {
Workflow workflow = xmlWorkflowFactory.getWorkflow(thisCollection);
LinkedHashMap<String, Role> result = new LinkedHashMap<String, Role>();
if (workflow != null) {
//Make sure we find one
HashMap<String, Role> allRoles = workflow.getRoles();
//We have retrieved all our roles, not get the ones which can be configured by the collection
for (String roleId : allRoles.keySet()) {
Role role = allRoles.get(roleId);
// We just require the roles which have a scope of collection
if (!role.isInternal()) {
result.put(roleId, role);
}
}
}
return result;
}
public static Group getRoleGroup(Context context, Collection collection, Role role) throws SQLException {
if (role.getScope() == Role.Scope.REPOSITORY) {
return groupService.findByName(context, role.getName());
} else
if (role.getScope() == Role.Scope.COLLECTION) {
CollectionRole collectionRole = collectionRoleService.find(context, collection, role.getId());
if (collectionRole == null)
return null;
return collectionRole.getGroup();
} else
if (role.getScope() == Role.Scope.ITEM) {
}
return null;
}
// public static List<String> getAllUsedStepIdentifiers(Context context) throws SQLException {
// TableRowIterator tri = DatabaseManager.queryTable(context, "cwf_claimtask", "SELECT DISTINCT step_id FROM cwf_pooltask UNION SELECT DISTINCT step_id FROM cwf_claimtask");
// List<String> result = new ArrayList<String>();
// while(tri.hasNext()) {
// TableRow row = tri.next();
// result.add(row.getStringColumn("step_id"));
// }
// return result;
// }
}