TaskCommandServlet.java 16.8 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.adobe.granite.taskmanagement.Task
 *  com.adobe.granite.taskmanagement.TaskManager
 *  com.adobe.granite.taskmanagement.TaskManagerException
 *  com.adobe.granite.taskmanagement.TaskManagerFactory
 *  com.adobe.granite.workflow.exec.Status
 *  javax.jcr.RepositoryException
 *  javax.jcr.Session
 *  javax.servlet.Servlet
 *  javax.servlet.ServletException
 *  javax.servlet.ServletInputStream
 *  org.apache.commons.io.IOUtils
 *  org.apache.felix.scr.annotations.Component
 *  org.apache.felix.scr.annotations.Properties
 *  org.apache.felix.scr.annotations.Property
 *  org.apache.felix.scr.annotations.Service
 *  org.apache.sling.api.SlingHttpServletRequest
 *  org.apache.sling.api.SlingHttpServletResponse
 *  org.apache.sling.api.request.RequestPathInfo
 *  org.apache.sling.api.resource.Resource
 *  org.apache.sling.api.resource.ResourceResolver
 *  org.apache.sling.api.servlets.SlingAllMethodsServlet
 *  org.apache.sling.commons.json.JSONException
 *  org.apache.sling.commons.json.JSONObject
 *  org.apache.sling.commons.json.io.JSONWriter
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.granite.taskmanagement.impl.servlet;

import com.adobe.granite.taskmanagement.Task;
import com.adobe.granite.taskmanagement.TaskManager;
import com.adobe.granite.taskmanagement.TaskManagerException;
import com.adobe.granite.taskmanagement.TaskManagerFactory;
import com.adobe.granite.taskmanagement.impl.service.TaskManagerImpl;
import com.adobe.granite.taskmanagement.impl.servlet.TaskJSONField;
import com.adobe.granite.taskmanagement.impl.servlet.TaskServletUtils;
import com.adobe.granite.workflow.exec.Status;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import org.apache.commons.io.IOUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.request.RequestPathInfo;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.apache.sling.commons.json.io.JSONWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component
@Service(value={Servlet.class})
@Properties(value={@Property(name="sling.servlet.paths", value={"/libs/granite/taskmanager/createtask", "/libs/granite/taskmanager/updatetask", "/libs/granite/taskmanager/deletetask"})})
public class TaskCommandServlet
extends SlingAllMethodsServlet {
    private static final Logger logger = LoggerFactory.getLogger(TaskCommandServlet.class);
    protected static final String CREATE_TASK_PATH = "/libs/granite/taskmanager/createtask";
    protected static final String UPDATE_TASK_PATH = "/libs/granite/taskmanager/updatetask";
    protected static final String DELETE_TASK_PATH = "/libs/granite/taskmanager/deletetask";
    private static final String PARNAME_TASK_ID = "taskId";
    private static final String PARNAME_FROM_RESOURCE = "fromResource";

    protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
        logger.debug("{}.doPost called", (Object)this.getClass().getName());
        ResourceResolver resolver = request.getResourceResolver();
        RequestPathInfo pathInfo = request.getRequestPathInfo();
        boolean fromResource = Boolean.parseBoolean(request.getParameter("fromResource"));
        TaskManager taskManager = null;
        try {
            JSONObject jsonTask;
            String taskId = request.getParameter("taskId");
            Task resultingTask = null;
            if ("/libs/granite/taskmanager/createtask".equals(pathInfo.getResourcePath())) {
                taskManager = (TaskManager)resolver.adaptTo(TaskManager.class);
                jsonTask = this.readJSONTaskFromRequest(request);
                resultingTask = this.createTaskFromJSON(taskManager, jsonTask);
            } else if ("/libs/granite/taskmanager/updatetask".equals(pathInfo.getResourcePath())) {
                jsonTask = this.readJSONTaskFromRequest(request);
                if (taskId == null) {
                    throw new ServletException("taskId parameter required to update tasks");
                }
                taskManager = this.getTaskManager(resolver, fromResource, taskId, "set_property");
                String selectedAction = request.getParameter("selectedAction");
                resultingTask = this.updateTaskFromJSON(taskManager, jsonTask, taskId, selectedAction);
            } else if ("/libs/granite/taskmanager/deletetask".equals(pathInfo.getResourcePath())) {
                if (taskId == null) {
                    throw new ServletException("taskId parameter required to update tasks");
                }
                taskManager = this.getTaskManager(resolver, fromResource, taskId, "remove");
                taskManager.deleteTask(taskId);
            } else {
                throw new ServletException(MessageFormat.format("Unknown task command {0}", pathInfo.getResourcePath()));
            }
            if (resultingTask != null) {
                response.setContentType("application/json");
                response.setCharacterEncoding("utf-8");
                JSONWriter w = new JSONWriter((Writer)response.getWriter());
                w.setTidy(true);
                TaskServletUtils.writeTaskInfo(w, resultingTask);
            }
        }
        catch (Exception e) {
            logger.error("Failed to create/update the task", (Throwable)e);
            response.setStatus(400);
        }
    }

    private TaskManager getTaskManager(ResourceResolver resolver, boolean fromResource, String taskId, String permission) throws ServletException {
        TaskManager taskManager = null;
        if (fromResource) {
            if (taskId == null) {
                throw new ServletException("taskId parameter required");
            }
            if (this.hasWriteAccess(resolver, taskId, permission)) {
                Resource taskResource = resolver.getResource(taskId);
                taskManager = (TaskManager)taskResource.adaptTo(TaskManager.class);
            } else {
                taskManager = (TaskManager)resolver.adaptTo(TaskManager.class);
            }
        }
        if (taskManager == null) {
            taskManager = (TaskManager)resolver.adaptTo(TaskManager.class);
        }
        return taskManager;
    }

    private boolean hasWriteAccess(ResourceResolver resourceResolver, String taskId, String permission) {
        Session session = (Session)resourceResolver.adaptTo(Session.class);
        try {
            return session.hasPermission(taskId, permission);
        }
        catch (RepositoryException e) {
            logger.error("error checking access for task: " + taskId, (Throwable)e);
            return false;
        }
    }

    private JSONObject readJSONTaskFromRequest(SlingHttpServletRequest request) throws TaskManagerException, JSONException, IOException {
        JSONObject jsonTask;
        if (request.getContentType() != null && request.getContentType().startsWith("application/x-www-form-urlencoded")) {
            jsonTask = this.extractJSONTaskFromUrlEncoded(request);
        } else {
            String jsonPayload = TaskCommandServlet.readJSON(request);
            jsonTask = new JSONObject(jsonPayload);
        }
        return jsonTask;
    }

    private JSONObject extractJSONTaskFromUrlEncoded(SlingHttpServletRequest request) throws TaskManagerException, JSONException {
        JSONObject task = new JSONObject();
        JSONObject properties = new JSONObject();
        Map parameterMap = request.getParameterMap();
        for (String key : parameterMap.keySet()) {
            if ("task:id".equals(key)) {
                task.put(TaskJSONField.TASK_ID.getValue(), (Object)this.getStringParameterValue(parameterMap, key));
                continue;
            }
            if ("task:taskType".equals(key)) {
                task.put(TaskJSONField.TASK_TYPE_NAME.getValue(), (Object)this.getStringParameterValue(parameterMap, key));
                continue;
            }
            if ("task:parentTaskId".equals(key)) {
                task.put(TaskJSONField.PARENT_TASK_ID.getValue(), (Object)this.getStringParameterValue(parameterMap, key));
                continue;
            }
            if ("task:description".equals(key)) {
                task.put(TaskJSONField.DESCRIPTION.getValue(), (Object)this.getStringParameterValue(parameterMap, key));
                continue;
            }
            if ("task:instructions".equals(key)) {
                task.put(TaskJSONField.INSTRUCTIONS.getValue(), (Object)this.getStringParameterValue(parameterMap, key));
                continue;
            }
            if ("task:owner".equals(key)) {
                task.put(TaskJSONField.OWNER_ID.getValue(), (Object)this.getStringParameterValue(parameterMap, key));
                continue;
            }
            if ("task:name".equals(key)) {
                task.put(TaskJSONField.NAME.getValue(), (Object)this.getStringParameterValue(parameterMap, key));
                continue;
            }
            if ("task:status".equals(key)) {
                task.put(TaskJSONField.STATUS.getValue(), (Object)this.getStringParameterValue(parameterMap, key));
                continue;
            }
            if (!key.startsWith("task:")) continue;
            String trimKey = key.substring("task:".length());
            properties.put(trimKey, (Object)this.getStringParameterValue(parameterMap, key));
        }
        task.put(TaskJSONField.PROPERTIES.getValue(), (Object)properties);
        return task;
    }

    private String getStringParameterValue(Map parameterMap, String key) {
        if (parameterMap == null || key == null) {
            return null;
        }
        Object result = parameterMap.get(key);
        if (result.getClass().isArray()) {
            Object[] arrayResult = (Object[])result;
            if (arrayResult.length > 0) {
                return arrayResult[0].toString();
            }
            return null;
        }
        return result.toString();
    }

    private static String readString(JSONObject object, String key) throws JSONException {
        if (object.has(key)) {
            return object.getString(key);
        }
        return null;
    }

    private Task updateTaskFromJSON(TaskManager taskManager, JSONObject jsonTask, String taskId, String selectedAction) throws TaskManagerException, JSONException {
        Task task = taskManager.getTask(taskId);
        Iterator keys = jsonTask.keys();
        Status newStatus = null;
        block15 : while (keys.hasNext()) {
            String key = (String)keys.next();
            TaskJSONField field = TaskJSONField.getFieldFromKey(key);
            if (field == null) {
                logger.debug("Unknown property posted: {}", (Object)key);
                throw new TaskManagerException(MessageFormat.format("Unknown property [{0}] posted while attempting to update a task", key));
            }
            String value = TaskCommandServlet.readString(jsonTask, key);
            switch (field) {
                case DESCRIPTION: {
                    task.setDescription(value);
                    break;
                }
                case INSTRUCTIONS: {
                    task.setInstructions(value);
                    break;
                }
                case NAME: {
                    task.setName(value);
                    break;
                }
                case OWNER_ID: {
                    task.setCurrentAssignee(value);
                    break;
                }
                case CONTENT_PATH: {
                    task.setContentPath(value);
                    break;
                }
                case PROPERTIES: {
                    JSONObject properties = jsonTask.getJSONObject(TaskJSONField.PROPERTIES.getValue());
                    if (properties == null) continue block15;
                    Iterator iter = properties.keys();
                    while (iter.hasNext()) {
                        String propertyName = (String)iter.next();
                        String propertyValue = properties.getString(propertyName);
                        task.setProperty(propertyName, (Object)propertyValue);
                    }
                    continue block15;
                }
                case STATUS: {
                    if (task.getStatus().name().equals(value)) continue block15;
                    try {
                        newStatus = Status.valueOf((String)value.toUpperCase());
                        break;
                    }
                    catch (IllegalArgumentException e) {
                        throw new TaskManagerException(MessageFormat.format("Unknown task status [{0}]", value));
                    }
                }
                case TASK_TYPE_NAME: {
                    logger.debug("Property [{}] ignored during task update", (Object)key);
                    break;
                }
                default: {
                    logger.debug("Property [{}] ignored during task update", (Object)key);
                }
            }
        }
        Task result = null;
        result = Status.COMPLETE == newStatus && taskManager instanceof TaskManagerImpl ? ((TaskManagerImpl)taskManager).saveTask(task, false) : taskManager.saveTask(task);
        if (newStatus != null) {
            switch (newStatus) {
                case COMPLETE: {
                    taskManager.completeTask(taskId, selectedAction);
                    result = taskManager.getTask(taskId);
                    break;
                }
                default: {
                    throw new TaskManagerException(MessageFormat.format("Unable to change status to [{0}]", new Object[]{newStatus}));
                }
            }
        }
        return result;
    }

    private Task createTaskFromJSON(TaskManager taskManager, JSONObject jsonTask) throws TaskManagerException, JSONException {
        String taskType = TaskCommandServlet.readString(jsonTask, TaskJSONField.TASK_TYPE_NAME.getValue()) == null ? "Default" : TaskCommandServlet.readString(jsonTask, TaskJSONField.TASK_TYPE_NAME.getValue());
        Task task = taskManager.getTaskManagerFactory().newTask(taskType);
        task.setName(TaskCommandServlet.readString(jsonTask, TaskJSONField.NAME.getValue()));
        task.setDescription(TaskCommandServlet.readString(jsonTask, TaskJSONField.DESCRIPTION.getValue()));
        task.setInstructions(TaskCommandServlet.readString(jsonTask, TaskJSONField.INSTRUCTIONS.getValue()));
        task.setCurrentAssignee(TaskCommandServlet.readString(jsonTask, TaskJSONField.OWNER_ID.getValue()));
        task.setContentPath(TaskCommandServlet.readString(jsonTask, TaskJSONField.CONTENT_PATH.getValue()));
        JSONObject properties = null;
        if (jsonTask.has(TaskJSONField.PROPERTIES.getValue())) {
            properties = jsonTask.getJSONObject(TaskJSONField.PROPERTIES.getValue());
        }
        if (properties != null) {
            Iterator iter = properties.keys();
            while (iter.hasNext()) {
                String propertyName = (String)iter.next();
                String propertyValue = properties.getString(propertyName);
                task.setProperty(propertyName, (Object)propertyValue);
            }
        }
        String parentTaskId = this.getJSONValueOrNull(jsonTask, TaskJSONField.PARENT_TASK_ID.getValue());
        Task taskCreationResult = null;
        taskCreationResult = parentTaskId != null ? taskManager.createTask(parentTaskId, task) : taskManager.createTask(task);
        return taskCreationResult;
    }

    private String getJSONValueOrNull(JSONObject jsonTask, String parentTaskId) {
        try {
            return jsonTask.getString(parentTaskId);
        }
        catch (JSONException e) {
            return null;
        }
    }

    public static String readJSON(SlingHttpServletRequest request) throws IOException {
        return IOUtils.toString((InputStream)request.getInputStream(), (String)"utf-8");
    }

    public static String readJSON(BufferedReader reader) throws IOException {
        String json = "";
        String line = reader.readLine();
        while (line != null) {
            json = json + line;
            line = reader.readLine();
        }
        return json;
    }

}