Java tutorial
/* * This file is part of Mockey, a tool for testing application * interactions over HTTP, with a focus on testing web services, * specifically web applications that consume XML, JSON, and HTML. * * Copyright (C) 2009-2010 Authors: * * chad.lafontaine (chad.lafontaine AT gmail DOT com) * neil.cronin (neil AT rackle DOT com) * lorin.kobashigawa (lkb AT kgawa DOT com) * rob.meyer (rob AT bigdis DOT com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ package com.mockey.ui; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.json.JSONException; import org.json.JSONObject; import com.mockey.model.ApiDocAttribute; import com.mockey.model.ApiDocFieldValue; import com.mockey.model.ApiDocRequest; import com.mockey.model.ApiDocResponse; import com.mockey.model.ApiDocService; import com.mockey.model.PlanItem; import com.mockey.model.Service; import com.mockey.model.ServicePlan; import com.mockey.storage.IApiStorage; import com.mockey.storage.IApiStorageInMemory; import com.mockey.storage.IMockeyStorage; import com.mockey.storage.StorageRegistry; /** * Management of SAVE, DELETE, or SET for a Service Plan, in addition to HTTP * Documentation. * * @author chadlafontaine * */ public class ServicePlanSetupServlet extends HttpServlet implements ServicePlanConfigurationAPI { private static final long serialVersionUID = -2964632050151431391L; private Log log = LogFactory.getLog(ServicePlanSetupServlet.class); private IMockeyStorage store = StorageRegistry.MockeyStorage; private IApiStorage apiStore = IApiStorageInMemory.getInstance(); /** * Loads up the HTTP API Documentation in memory for this service. The HTTP * API information to describe this servlet's REQUEST and RESPONSE messaging * is displayed to the end user via the Service API help page. */ public void init() throws ServletException { // ***************************** // THIS SERVICE API DESCRIPTION CONTRACT // ***************************** // This information is used in the API JSP document, used to describe // how to make setting changes from a head-less client. if (apiStore.getApiDocServiceByName(API_SERVICE_PLAN_CONFIGURATION_NAME) == null) { ApiDocService apiDocService = new ApiDocService(); apiDocService.setName(API_SERVICE_PLAN_CONFIGURATION_NAME); apiDocService.setDescription( "If you need Mockey to load a specific Service Plan, then this API may meet your needs. When to use: your automated test scripts need Mockey in a certain state of mind."); // TODO: We need to use a pattern matching replace e.g. ${0} ${1} // with array ["a", "b"] for VALUES apiDocService.setServicePath("/plan/setup"); // ***************************** // REQUEST DEFINITION // ***************************** ApiDocRequest apiDocRequest = new ApiDocRequest(); // Parameter - 'action' ApiDocAttribute reqAttributeAction = new ApiDocAttribute(); reqAttributeAction.setFieldName(API_SETPLAN_PARAMETER_ACTION); reqAttributeAction.addFieldValues(new ApiDocFieldValue(API_SETPLAN_PARAMETER_ACTION_VALUE_DELETE_PLAN, "Delete the service plan definition given a valid plan_id parameter.")); reqAttributeAction.addFieldValues(new ApiDocFieldValue(API_SETPLAN_PARAMETER_ACTION_VALUE_SAVE_PLAN, "Saves current configuration settings as a service plan definition.")); reqAttributeAction.addFieldValues(new ApiDocFieldValue(API_SETPLAN_PARAMETER_ACTION_VALUE_SET_PLAN, "Sets a service plan given a valid plan_id parameter.")); apiDocRequest.addAttribute(reqAttributeAction); // Parameter - 'plan_id' ApiDocAttribute reqAttributePlanId = new ApiDocAttribute(); reqAttributePlanId.setFieldName(API_SETPLAN_PARAMETER_PLAN_ID); reqAttributePlanId .addFieldValues(new ApiDocFieldValue("[identifier]", "A valid service plan identifier.")); reqAttributePlanId.setExample("123"); apiDocRequest.addAttribute(reqAttributePlanId); // Parameter - 'service_plan_name' ApiDocAttribute reqAttributePlanName = new ApiDocAttribute(); reqAttributePlanName.setFieldName(API_SET_SAVE_OR_UPDATE_PARAMETER_PLAN_NAME); reqAttributePlanName.addFieldValues(new ApiDocFieldValue("[string]", "The service plan name needed to create or save/update. If plan_id not provided, then this value is used to locate the service plan for setting or updating.")); reqAttributePlanName.setExample("The Gold Service Plan"); apiDocRequest.addAttribute(reqAttributePlanName); // Parameter - 'type' ApiDocAttribute reqAttributeType = new ApiDocAttribute(); reqAttributeType.setFieldName(API_SETPLAN_PARAMETER_TYPE); reqAttributeType.addFieldValues(new ApiDocFieldValue("json", "Response will be in JSON. Any other value for 'type' is undefined and you may experience a 302.")); apiDocRequest.addAttribute(reqAttributeType); apiDocService.setApiRequest(apiDocRequest); // Parameter - 'type' ApiDocAttribute reqTransientState = new ApiDocAttribute(); reqTransientState.setFieldName(API_TRANSIENT_STATE); reqTransientState.addFieldValues(new ApiDocFieldValue("[boolean]", "If available and set to 'true', then all settings in this call will be in-memory only, not persisted to the file system. Otherwise, state settings will be written to the file system.")); apiDocRequest.addAttribute(reqTransientState); apiDocService.setApiRequest(apiDocRequest); // ***************************** // RESPONSE DEFINITION // ***************************** ApiDocResponse apiResponse = new ApiDocResponse(); // Building a JSON RESPONSE example try { JSONObject jsonResponseObject = new JSONObject(); JSONObject jsonResultObject = new JSONObject(); jsonResultObject.put("success", "Some informative coaching message. If success isn't a value, then maybe you have a 'fail' message."); jsonResultObject.put("planId", "1234"); jsonResultObject.put("planName", "Some service name"); jsonResponseObject.put("result", jsonResultObject); apiResponse.setExample(jsonResponseObject.toString()); } catch (Exception e) { log.error("Unabel to build a sample JSON message. ", e); } // Response attribute 'planId' ApiDocAttribute resAttributePlanId = new ApiDocAttribute(); resAttributePlanId.setFieldName("planId"); resAttributePlanId.setFieldDescription("Identifier of a Service Plan"); apiResponse.addAttribute(resAttributePlanId); // Response attribute 'planName' ApiDocAttribute resAttributePlanName = new ApiDocAttribute(); resAttributePlanName.setFieldName("planName"); resAttributePlanName.setFieldDescription("Name of a Service Plan"); apiResponse.addAttribute(resAttributePlanName); // Response attribute 'success' ApiDocAttribute resAttributeSuccess = new ApiDocAttribute(); resAttributeSuccess.setFieldName("success"); resAttributeSuccess.setFieldDescription( "Successfully set, deleted, or saved a plan. You get 'fail' or 'success', not both."); apiResponse.addAttribute(resAttributeSuccess); ApiDocAttribute resAttributeFail = new ApiDocAttribute(); resAttributeFail.setFieldName("fail"); resAttributeFail.setFieldDescription( "Failed to set, delete, or save a plan. You get 'fail' or 'success', not both."); apiResponse.addAttribute(resAttributeFail); apiDocService.setApiResponse(apiResponse); apiStore.saveOrUpdateService(apiDocService); } } /** * * * @param req * basic request * @param resp * basic resp * @throws ServletException * basic * @throws IOException * basic */ public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try { // API BUSINESS LOGIC // log.debug("Service Plan setup/delete"); ServicePlan servicePlan = null; Long servicePlanId = null; List<Service> allServices = store.getServices(); // ********************* // BEST EFFORT HERE. // We try to find the service by ID. // If not found, we try by NAME. // Otherwise, let the rest of the logic do its thing. // ********************* try { servicePlanId = new Long(req.getParameter(API_SETPLAN_PARAMETER_PLAN_ID)); servicePlan = store.getServicePlanById(servicePlanId); } catch (Exception e) { if (req.getParameter(API_SETPLAN_PARAMETER_PLAN_ID) != null) { log.debug("No service plan with ID '" + req.getParameter(API_SETPLAN_PARAMETER_PLAN_ID) + "' found.", e); } } if (servicePlan == null) { try { String servicePlanName = req.getParameter(API_SET_SAVE_OR_UPDATE_PARAMETER_PLAN_NAME); servicePlan = store.getServicePlanByName(servicePlanName.trim()); } catch (Exception e) { if (req.getParameter(API_SET_SAVE_OR_UPDATE_PARAMETER_PLAN_NAME) != null) { log.debug( "No service plan with NAME '" + req.getParameter(API_SET_SAVE_OR_UPDATE_PARAMETER_PLAN_NAME) + "' found.", e); } } } JSONObject jsonResultObject = new JSONObject(); String action = req.getParameter(API_SETPLAN_PARAMETER_ACTION); String transientState = req.getParameter(API_TRANSIENT_STATE); try { if (transientState != null) { servicePlan.setTransientState(new Boolean(transientState)); } } catch (Exception e) { log.debug("ServicePlan not set to transient state but a value was given as: " + transientState); } if (API_SETPLAN_PARAMETER_ACTION_VALUE_DELETE_PLAN.equals(action)) { JSONObject jsonObject = new JSONObject(); try { store.deleteServicePlan(servicePlan); jsonObject.put("success", "Service plan '" + servicePlan.getName() + "' deleted"); jsonObject.put("planId", "" + servicePlan.getId()); jsonObject.put("planName", "" + servicePlan.getName()); } catch (Exception e) { jsonObject.put("fail", "Service plan not deleted. Please check your logs for insight."); } resp.setContentType("application/json"); PrintWriter out = resp.getWriter(); jsonResultObject.put("result", jsonObject); out.println(jsonResultObject.toString()); out.flush(); out.close(); return; } else if (API_SETPLAN_PARAMETER_ACTION_VALUE_SET_PLAN.equals(action) && servicePlan != null) { JSONObject jsonObject = new JSONObject(); try { setPlan(servicePlan); String msg = "Service plan " + servicePlan.getName() + " set"; jsonObject.put("success", msg); jsonObject.put("planid", "" + servicePlan.getId()); jsonObject.put("planName", "" + servicePlan.getName()); Util.saveSuccessMessage(msg, req); // For redirect } catch (Exception e) { jsonObject.put("fail", "Service plan not set. Please check your logs for insight."); } resp.setContentType("application/json"); PrintWriter out = resp.getWriter(); jsonResultObject.put("result", jsonObject); out.println(jsonResultObject.toString()); out.flush(); out.close(); return; } else if (API_SETPLAN_PARAMETER_ACTION_VALUE_SAVE_PLAN.equals(action)) { if (servicePlan == null) { servicePlan = new ServicePlan(); } // *************************** // LET'S PREVENT EMPTY PLAN NAMES // *************************** String servicePlanName = req.getParameter(API_SET_SAVE_OR_UPDATE_PARAMETER_PLAN_NAME); if (servicePlanName == null) { // If possible, carry over the name from an existing Plan. servicePlanName = servicePlan.getName(); } // If all fails, inject a name. if (servicePlanName == null || servicePlanName.trim().length() == 0) { servicePlanName = "Plan (auto-generated-name)"; } servicePlan.setName(servicePlanName.trim()); // *************************** // SAVE/UPDATE THE PLAN // *************************** ServicePlan savedServicePlan = createOrUpdatePlan(servicePlan); // *************************** // SAVE/UPDATE THE PLAN // *************************** resp.setContentType("application/json"); PrintWriter out = resp.getWriter(); String msg = "Service plan " + servicePlan.getName() + " saved"; // HACK: For redirect IF JavaScript decides to (if type is not // JSON) if (!"json".equalsIgnoreCase(req.getParameter(API_SETPLAN_PARAMETER_TYPE))) { Util.saveSuccessMessage(msg, req); } // JSON response JSONObject jsonObject = new JSONObject(); jsonObject.put("success", msg); jsonObject.put("planid", "" + savedServicePlan.getId()); jsonObject.put("planName", "" + savedServicePlan.getName()); jsonResultObject.put("result", jsonObject); out.println(jsonResultObject.toString()); out.flush(); out.close(); return; } req.setAttribute("services", allServices); req.setAttribute("plans", store.getServicePlans()); RequestDispatcher dispatch = req.getRequestDispatcher("/home.jsp"); dispatch.forward(req, resp); } catch (JSONException jsonException) { throw new ServletException(jsonException); } } private ServicePlan createOrUpdatePlan(ServicePlan servicePlan) { List<PlanItem> planItemList = new ArrayList<PlanItem>(); for (Service service : store.getServices()) { PlanItem planItem = new PlanItem(); planItem.setHangTime(service.getHangTime()); planItem.setServiceId(service.getId()); planItem.setScenarioId(service.getDefaultScenarioId()); planItem.setServiceResponseType(service.getServiceResponseType()); planItemList.add(planItem); } servicePlan.setPlanItemList(planItemList); return store.saveOrUpdateServicePlan(servicePlan); } private void setPlan(ServicePlan servicePlan) { if (servicePlan == null) { servicePlan = new ServicePlan(); } for (PlanItem planItem : servicePlan.getPlanItemList()) { Service service = store.getServiceById(planItem.getServiceId()); if (service != null) { service.setHangTime(planItem.getHangTime()); service.setDefaultScenarioId(planItem.getScenarioId()); service.setServiceResponseType(planItem.getServiceResponseType()); store.saveOrUpdateService(service); } } } }