/** Execute the Web Script encapsulated by this Web Script Runtime */ public final void executeScript() { final boolean debug = logger.isDebugEnabled(); long startRuntime = 0L; if (debug) startRuntime = System.nanoTime(); final String method = getScriptMethod(); String scriptUrl = null; Match match = null; try { // extract script url scriptUrl = getScriptUrl(); if (scriptUrl == null || scriptUrl.length() == 0) { throw new WebScriptException( HttpServletResponse.SC_BAD_REQUEST, "Script URL not specified"); } if (debug) logger.debug( "(Runtime=" + getName() + ", Container=" + container.getName() + ") Processing script url (" + method + ") " + scriptUrl); WebScriptRequest scriptReq = null; WebScriptResponse scriptRes = null; Authenticator auth = null; RequiredAuthentication containerRequiredAuth = container.getRequiredAuthentication(); if (!containerRequiredAuth.equals(RequiredAuthentication.none)) { // Create initial request & response scriptReq = createRequest(null); scriptRes = createResponse(); auth = createAuthenticator(); if (debug) logger.debug( "(Runtime=" + getName() + ", Container=" + container.getName() + ") Container requires pre-auth: " + containerRequiredAuth); boolean preAuth = true; if (auth != null && auth.emptyCredentials()) { // check default (unauthenticated) domain match = container.getRegistry().findWebScript(method, scriptUrl); if ((match != null) && (match .getWebScript() .getDescription() .getRequiredAuthentication() .equals(RequiredAuthentication.none))) { preAuth = false; } } if (preAuth && (!container.authenticate(auth, containerRequiredAuth))) { return; // return response (eg. prompt for un/pw if status is 401 or redirect) } } if (match == null) { match = container.getRegistry().findWebScript(method, scriptUrl); } if (match == null || match.getKind() == Match.Kind.URI) { if (match == null) { String msg = "Script url " + scriptUrl + " does not map to a Web Script."; if (debug) logger.debug(msg); throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, msg); } else { String msg = "Script url " + scriptUrl + " does not support the method " + method; if (debug) logger.debug(msg); throw new WebScriptException(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg); } } // create web script request & response scriptReq = createRequest(match); scriptRes = createResponse(); if (auth == null) { // not pre-authenticated auth = createAuthenticator(); } if (debug) logger.debug("Agent: " + scriptReq.getAgent()); long startScript = System.nanoTime(); final WebScript script = match.getWebScript(); final Description description = script.getDescription(); try { if (debug) { String reqFormat = scriptReq.getFormat(); String format = (reqFormat == null || reqFormat.length() == 0) ? "[undefined]" : reqFormat; Description desc = scriptReq.getServiceMatch().getWebScript().getDescription(); logger.debug( "Invoking Web Script " + description.getId() + " (format " + format + ", style: " + desc.getFormatStyle() + ", default: " + desc.getDefaultFormat() + ")"); } executeScript(scriptReq, scriptRes, auth); } finally { if (debug) { long endScript = System.nanoTime(); logger.debug( "Web Script " + description.getId() + " executed in " + (endScript - startScript) / 1000000f + "ms"); } } } catch (Throwable e) { if (beforeProcessError(match, e)) { if (e instanceof WebScriptException && (((WebScriptException) e).getStatus() == HttpServletResponse.SC_NOT_FOUND || ((WebScriptException) e).getStatus() == HttpServletResponse.SC_UNAUTHORIZED)) { // debug level output for "missing" WebScripts and API URLs entered incorrectly String errorCode = ((WebScriptException) e).getStatus() == HttpServletResponse.SC_NOT_FOUND ? "NOT FOUND" : "UNAUTHORIZED"; logger.debug("Webscript did not execute. (" + errorCode + "): " + e.getMessage()); } // log error on server so its not swallowed and lost else if (logger.isErrorEnabled()) { logger.error( "Exception from executeScript - redirecting to status template error: " + e.getMessage(), e); } // setup context WebScriptRequest req = createRequest(match); WebScriptResponse res = createResponse(); String format = req.getFormat(); // extract status code, if specified int statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR; StatusTemplate statusTemplate = null; Map<String, Object> statusModel = null; if (e instanceof WebScriptException) { WebScriptException we = (WebScriptException) e; statusCode = we.getStatus(); statusTemplate = we.getStatusTemplate(); statusModel = we.getStatusModel(); } // retrieve status template for response rendering if (statusTemplate == null) { // locate status template // NOTE: search order... // 1) root located <status>.ftl // 2) root located <format>.status.ftl // 3) root located status.ftl statusTemplate = getStatusCodeTemplate(statusCode); String validTemplatePath = container .getTemplateProcessorRegistry() .findValidTemplatePath(statusTemplate.getPath()); if (validTemplatePath == null) { if (format != null && format.length() > 0) { // if we have a format try and get the format specific status template statusTemplate = getFormatStatusTemplate(format); validTemplatePath = container .getTemplateProcessorRegistry() .findValidTemplatePath(statusTemplate.getPath()); } // if we don't have a valid template path get the default status template if (validTemplatePath == null) { statusTemplate = getStatusTemplate(); validTemplatePath = container .getTemplateProcessorRegistry() .findValidTemplatePath(statusTemplate.getPath()); } // throw error if a status template could not be found if (validTemplatePath == null) { throw new WebScriptException( "Failed to find status template " + statusTemplate.getPath() + " (format: " + statusTemplate.getFormat() + ")"); } } } // create basic model for all information known at this point, if one hasn't been // pre-provided if (statusModel == null || statusModel.equals(Collections.EMPTY_MAP)) { statusModel = new HashMap<String, Object>(8, 1.0f); statusModel.putAll(container.getTemplateParameters()); statusModel.put("url", createURLModel(req)); if (match != null && match.getWebScript() != null) { statusModel.put("webscript", match.getWebScript().getDescription()); } } // add status to model Status status = new Status(); status.setCode(statusCode); status.setMessage(e.getMessage() != null ? e.getMessage() : e.toString()); if (exceptionLogger.isDebugEnabled()) { status.setException(e); } statusModel.put("status", status); // render output String mimetype = container.getFormatRegistry().getMimeType(req.getAgent(), statusTemplate.getFormat()); if (mimetype == null) { throw new WebScriptException( "Web Script format '" + statusTemplate.getFormat() + "' is not registered"); } if (debug) { logger.debug("Force success status header in response: " + req.forceSuccessStatus()); logger.debug( "Sending status " + statusCode + " (Template: " + statusTemplate.getPath() + ")"); logger.debug("Rendering response: content type=" + mimetype); } Cache cache = new Cache(); cache.setNeverCache(true); res.setCache(cache); res.setStatus(req.forceSuccessStatus() ? HttpServletResponse.SC_OK : statusCode); res.setContentType(mimetype + ";charset=UTF-8"); try { String validTemplatePath = container .getTemplateProcessorRegistry() .findValidTemplatePath(statusTemplate.getPath()); TemplateProcessor statusProcessor = container.getTemplateProcessorRegistry().getTemplateProcessor(validTemplatePath); statusProcessor.process(validTemplatePath, statusModel, res.getWriter()); } catch (Exception e1) { logger.error("Internal error", e1); throw new WebScriptException("Internal error", e1); } } } finally { if (debug) { long endRuntime = System.nanoTime(); logger.debug( "Processed script url (" + method + ") " + scriptUrl + " in " + (endRuntime - startRuntime) / 1000000f + "ms"); } } }
/** * Executes the {@code ActionInstance} * * @throws com.netflix.scheduledactions.exceptions.ExecutionException */ public Execution execute(final ActionInstance actionInstance, String initiator) { if (actionInstance.isDisabled()) { return null; } final String actionInstanceId = actionInstance.getId(); final Execution execution = new Execution(delegateId, actionInstanceId); final String executionId = executionDao.createExecution(actionInstanceId, execution); logger.info("[{}] Created execution for actionInstance: {}", actionInstanceId, executionId); execution.getLogger().info(String.format("Created execution %s", executionId)); List<Execution> previousExecutions = getInCompleteExecutionsBefore(actionInstanceId, execution); if (previousExecutions.size() > 0) { ConcurrentExecutionStrategy strategy = actionInstance.getConcurrentExecutionStrategy(); switch (strategy) { case ALLOW: execution .getLogger() .info("Concurrent execution strategy is: ALLOW, allowing execution..."); logger.info( "[{}] actionInstance concurrent execution strategy is: ALLOW, allowing execution...", actionInstanceId); break; case REJECT: Status status = Status.SKIPPED; status.setMessage( String.format( "ConcurrentExecutionStrategy for ActionInstance %s is REJECT and it has incomplete executions", actionInstance)); execution.setStatus(status); execution.setStartTime(new Date()); execution.setEndTime(new Date()); logger.info( "[{}] actionInstance concurrent execution strategy is: REJECT, skipping execution", actionInstanceId); execution .getLogger() .info("Concurrent execution strategy is: REJECT, skipping execution"); executionDao.updateExecution(execution); return execution; case REPLACE: logger.info( "[{}] actionInstance concurrent execution strategy is: REPLACE, cancelling previous execution(s)", actionInstanceId); cancelPreviousExecutions(actionInstance, execution); break; default: break; } } logger.info("[{}] Submitting runnable for execution: {}", actionInstanceId, executionId); executeService.submit( new Runnable() { @Override public void run() { try { Action action = newInstance(actionInstance); execution.getLogger().info("Calling executor.execute()..."); logger.info( "[{}] Calling executor.execute() for execution {} ...", actionInstanceId, executionId); executor.execute(action, actionInstance, execution); } catch (ExecutionException e) { Status status = e.getStatus() != null ? e.getStatus() : Status.FAILED; status.setMessage(e.getMessage()); execution.setEndTime(new Date()); execution.setStatus(status); execution.getLogger().error("Exception occurred while executing action", e); } catch (Exception e) { Status status = Status.FAILED; status.setMessage( String.format( "Exception occurred while executing action %s: %s", actionInstance.getAction(), e.getMessage())); execution.getLogger().error("Exception occurred while executing action", e); execution.setEndTime(new Date()); execution.setStatus(status); } finally { executionDao.updateExecution(execution); } } }); return execution; }