/** * 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.app.webui.servlet.admin; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.sql.SQLException; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import org.dspace.app.util.Util; import org.dspace.app.webui.servlet.DSpaceServlet; import org.dspace.app.webui.util.CurateTaskResult; import org.dspace.app.webui.util.JSPManager; import org.dspace.app.webui.util.UIUtil; import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeManager; import org.dspace.content.Collection; import org.dspace.content.Community; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.core.ConfigurationManager; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.I18nUtil; import org.dspace.curate.Curator; import org.dspace.core.LogManager; import org.dspace.handle.HandleManager; /** * * @author Keiji Suzuki */ public class CurateServlet extends DSpaceServlet { // Name of queue used when tasks queued in Admin UI private static final String TASK_QUEUE_NAME = ConfigurationManager.getProperty("curate", "ui.queuename"); // curation status codes in Admin UI: key=status code, value=localized name private static final Map<String, String> statusMessages = new HashMap<String, String>(); // curation tasks to appear in admin UI: key=taskID, value=friendly name private static Map<String, String> allTasks = new LinkedHashMap<String, String>(); // named groups which display together in admin UI: key=groupID, value=friendly group name private static Map<String, String> taskGroups = new LinkedHashMap<String, String>(); // group membership: key=groupID, value=array of taskID private static Map<String, String[]> groupedTasks = new LinkedHashMap<String, String[]>(); static { try { setStatusMessages(); setAllTasks(); setTaskGroups(); setGroupedTasks(); } catch (Exception we) { // noop } } /** Logger */ private static Logger log = Logger.getLogger(CurateServlet.class); protected void doDSGet(Context context, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, SQLException, AuthorizeException { doDSPost(context, request, response); } protected void doDSPost(Context context, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, SQLException, AuthorizeException { String button = UIUtil.getSubmitButton(request, "submit"); // When task gropu is changed, no submit button is clicked. // Reset the submit button to inform the original page. if ("submit".equals(button)) { if (request.getParameter("community_id") != null) { button = "submit_community_select"; } else if (request.getParameter("collection_id") != null) { button = "submit_collection_select"; } else if (request.getParameter("item_id") != null) { button = "submit_item_select"; } else { button = "submit_main_select"; } } if (button.startsWith("submit_community_")) { Community community = Community.find(context, UIUtil.getIntParameter(request, "community_id")); request.setAttribute("community", community); if (!AuthorizeManager.isAdmin(context, community)) { throw new AuthorizeException("Only community admins are allowed to perform curation tasks"); } if ("submit_community_curate".equals(button)) { processCurateObject(context, request, community.getHandle()); } else if ("submit_community_queue".equals(button)) { processQueueObject(context, request, community.getHandle()); } showPage(request, response, "/tools/curate-community.jsp"); } else if (button.startsWith("submit_collection_")) { Collection collection = Collection.find(context, UIUtil.getIntParameter(request, "collection_id")); request.setAttribute("collection", collection); if (!AuthorizeManager.isAdmin(context, collection)) { throw new AuthorizeException("Only collection admins are allowed to perform curation tasks"); } if ("submit_collection_curate".equals(button)) { processCurateObject(context, request, collection.getHandle()); } else if ("submit_collection_queue".equals(button)) { processQueueObject(context, request, collection.getHandle()); } showPage(request, response, "/tools/curate-collection.jsp"); } else if (button.startsWith("submit_item_")) { Item item = Item.find(context, UIUtil.getIntParameter(request, "item_id")); request.setAttribute("item", item); if (!AuthorizeManager.isAdmin(context, item)) { throw new AuthorizeException("Only item admins are allowed to perform curation tasks"); } if ("submit_item_curate".equals(button)) { processCurateObject(context, request, item.getHandle()); } else if ("submit_item_queue".equals(button)) { processQueueObject(context, request, item.getHandle()); } showPage(request, response, "/tools/curate-item.jsp"); } else if (button.startsWith("submit_main_")) { String handle = request.getParameter("handle"); if (handle != null) { if (handle.endsWith("/0")) { if (!AuthorizeManager.isAdmin(context)) { throw new AuthorizeException("Only system admins are allowed to perform curation tasks over the site"); } } else { DSpaceObject dso = HandleManager.resolveToObject(context, handle); if (!AuthorizeManager.isAdmin(context, dso)) { throw new AuthorizeException("Only object (hdl:"+handle+") admins are allowed to perform curation tasks"); } } if ("submit_main_curate".equals(button)) { processCurateObject(context, request, handle); } else if ("submit_main_queue".equals(button)) { processQueueObject(context, request, handle); } else if ("submit_main_cancel".equals(button)) { handle = null; } request.setAttribute("handle", handle); } showPage(request, response, "/dspace-admin/curate-main.jsp"); } else { log.warn(LogManager.getHeader(context, "integrity_error", UIUtil .getRequestLogInfo(request))); JSPManager.showIntegrityError(request, response); } } private void showPage(HttpServletRequest request, HttpServletResponse response, String page) throws ServletException, IOException, SQLException, AuthorizeException { String group = request.getParameter("select_curate_group"); String groupOptions = getGroupSelectOptions(group); String taskOptions = getTaskSelectOptions(group); request.setAttribute("curate_group_options", groupOptions); request.setAttribute("curate_task_options", taskOptions); JSPManager.showJSP(request, response, page); } private void processCurateObject(Context context, HttpServletRequest request, String handle) { String task = request.getParameter("curate_task"); Curator curator = getCurator(task); boolean success = false; try { curator.curate(context, handle); success = true; } catch (Exception e) { curator.setResult(task, e.getMessage()); } request.setAttribute("task_result", getCurateMessage(context, curator, task, handle, success)); } private void processQueueObject(Context context, HttpServletRequest request, String handle) { String task = request.getParameter("curate_task"); Curator curator = getCurator(task); boolean success = false; try { curator.queue(context, handle, TASK_QUEUE_NAME); success = true; } catch (Exception e) { // no-op (any error should be logged by the Curator itself) } request.setAttribute("task_result", new CurateTaskResult("queue", getTaskName(task), handle, null, null, success)); } private CurateTaskResult getCurateMessage(Context context, Curator curator, String task, String handle, boolean success) { String status = statusMessages.get(String.valueOf(curator.getStatus(task))); if (status == null) { status = statusMessages.get("other"); } String result = curator.getResult(task); if (result == null) { result = I18nUtil.getMessage("org.dspace.app.webui.servlet.admin.CurationServlet.null-result", context); } return new CurateTaskResult("perform", getTaskName(task), handle, status, result, success); } private Curator getCurator(String task) { if (task != null && task.length() == 0) { task = null; } Curator curator = new Curator(); curator.addTask(task); curator.setInvoked(Curator.Invoked.INTERACTIVE); return curator; } private static void setStatusMessages() throws UnsupportedEncodingException { String statusCodes = ConfigurationManager.getProperty("curate", "ui.statusmessages"); for (String property : statusCodes.split(",")) { String[] keyValuePair = property.split("="); statusMessages.put(URLDecoder.decode(keyValuePair[0].trim(), "UTF-8"), URLDecoder.decode(keyValuePair[1].trim(), "UTF-8")); } } private static void setAllTasks() throws UnsupportedEncodingException { String properties = ConfigurationManager.getProperty("curate", "ui.tasknames"); for (String property : properties.split(",")) { String[] keyValuePair = property.split("="); allTasks.put(URLDecoder.decode(keyValuePair[0].trim(), "UTF-8"), URLDecoder.decode(keyValuePair[1].trim(), "UTF-8")); } } private static void setTaskGroups() throws UnsupportedEncodingException { String groups = ConfigurationManager.getProperty("curate", "ui.taskgroups"); if (groups != null) { for (String property : groups.split(",")) { String[] keyValuePair = property.split("="); taskGroups.put(URLDecoder.decode(keyValuePair[0].trim(), "UTF-8"), URLDecoder.decode(keyValuePair[1].trim(), "UTF-8")); } } } private static void setGroupedTasks() throws UnsupportedEncodingException { if (!taskGroups.isEmpty()) { Iterator<String> iterator = taskGroups.keySet().iterator(); while (iterator.hasNext()) { String groupID = iterator.next(); String memberList = ConfigurationManager.getProperty("curate", "ui.taskgroup" + "." + groupID); String[] members = memberList.split(","); groupedTasks.put(URLDecoder.decode(groupID, "UTF-8"), members); } } } /** * Get the string of html option elements for group selection * * @param group the short name / identifier for the group * @return the string of the html option elements * return "" if no group exists. */ private String getGroupSelectOptions(String group) { StringBuilder sb = new StringBuilder(); Iterator<String> iterator = taskGroups.keySet().iterator(); while (iterator.hasNext()) { String groupID = iterator.next(); sb.append("<option"); if (groupID.equals(group)) { sb.append(" selected=\"selected\""); } sb.append(" value=\"").append(groupID).append("\">") .append(taskGroups.get(groupID)).append("</option>\n"); } return sb.toString(); } /** * Get the string of html option elements for task selection of the specified task group * when no task group exists, made from all tasks * * @param group the short name / identifier for the group * @return the string of the html option elements */ private static String getTaskSelectOptions(String group) { StringBuilder sb = new StringBuilder(); if (groupedTasks.isEmpty()) { Iterator<String> iterator = allTasks.keySet().iterator(); while (iterator.hasNext()) { String task = iterator.next(); sb.append("<option value=\"").append(task).append("\">") .append(allTasks.get(task)).append("</option>\n"); } } else { if (group == null || "".equals(group)) { group = groupedTasks.keySet().iterator().next(); } String[] members = groupedTasks.get(group); if (members != null && members.length > 0) { for (String member : members) { Iterator<String> innerIterator = allTasks.keySet().iterator(); while (innerIterator.hasNext()) { String taskID = innerIterator.next().trim(); if (taskID.equals(member.trim())) { sb.append("<option value=\"").append(taskID).append("\">") .append(allTasks.get(taskID)).append("</option>\n"); } } } } } return sb.toString(); } /** * Retrieve UI "friendly" Task Name for display to user * * @param taskID the short name / identifier for the task * @return the User Friendly name for this task */ private String getTaskName(String taskID) { return allTasks.containsKey(taskID) ? allTasks.get(taskID) : taskID; } }