001 /** 002 * Copyright (c) 2010 Yahoo! Inc. All rights reserved. 003 * Licensed under the Apache License, Version 2.0 (the "License"); 004 * you may not use this file except in compliance with the License. 005 * You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software 010 * distributed under the License is distributed on an "AS IS" BASIS, 011 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 * See the License for the specific language governing permissions and 013 * limitations under the License. See accompanying LICENSE file. 014 */ 015 package org.apache.oozie.servlet; 016 017 import java.io.IOException; 018 import java.util.Arrays; 019 import java.util.Collections; 020 import java.util.Properties; 021 022 import javax.servlet.ServletException; 023 import javax.servlet.http.HttpServletRequest; 024 import javax.servlet.http.HttpServletResponse; 025 026 import org.apache.oozie.DagEngine; 027 import org.apache.oozie.DagEngineException; 028 import org.apache.oozie.ErrorCode; 029 import org.apache.oozie.client.rest.RestConstants; 030 import org.apache.oozie.service.CallbackService; 031 import org.apache.oozie.service.DagEngineService; 032 import org.apache.oozie.service.Services; 033 import org.apache.oozie.util.IOUtils; 034 import org.apache.oozie.util.PropertiesUtils; 035 import org.apache.oozie.util.XLog; 036 037 public class CallbackServlet extends JsonRestServlet { 038 private static final String INSTRUMENTATION_NAME = "callback"; 039 040 private static final ResourceInfo RESOURCE_INFO = 041 new ResourceInfo("", Arrays.asList("POST", "GET"), Collections.EMPTY_LIST); 042 043 public final static String CONF_MAX_DATA_LEN = "oozie.servlet.CallbackServlet.max.data.len"; 044 045 private static int maxDataLen; 046 047 private XLog log = null; 048 049 public CallbackServlet() { 050 super(INSTRUMENTATION_NAME, RESOURCE_INFO); 051 } 052 053 @Override 054 public void init() { 055 maxDataLen = Services.get().getConf().getInt(CONF_MAX_DATA_LEN, 2 * 1024); 056 } 057 058 /** 059 * GET callback 060 */ 061 @Override 062 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 063 String queryString = request.getQueryString(); 064 CallbackService callbackService = Services.get().get(CallbackService.class); 065 066 if (!callbackService.isValid(queryString)) { 067 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0402, queryString); 068 } 069 070 String actionId = callbackService.getActionId(queryString); 071 if (actionId == null) { 072 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0402, queryString); 073 } 074 int idx = actionId.lastIndexOf('@', actionId.length()); 075 String jobId; 076 if (idx == -1) { 077 jobId = actionId; 078 } 079 else { 080 jobId = actionId.substring(0, idx); 081 } 082 setLogInfo(jobId, actionId); 083 log = XLog.getLog(getClass()); 084 log.debug("Received a CallbackServlet.doGet() with query string " + queryString); 085 086 DagEngine dagEngine = Services.get().get(DagEngineService.class).getSystemDagEngine(); 087 try { 088 log.info(XLog.STD, "callback for action [{0}]", actionId); 089 dagEngine.processCallback(actionId, callbackService.getExternalStatus(queryString), null); 090 } 091 catch (DagEngineException ex) { 092 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex); 093 } 094 } 095 096 /** 097 * POST callback 098 */ 099 @Override 100 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, 101 IOException { 102 String queryString = request.getQueryString(); 103 CallbackService callbackService = Services.get().get(CallbackService.class); 104 105 if (!callbackService.isValid(queryString)) { 106 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0402, queryString); 107 } 108 109 String actionId = callbackService.getActionId(queryString); 110 if (actionId == null) { 111 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0402, queryString); 112 } 113 int idx = actionId.lastIndexOf('@', actionId.length()); 114 String jobId; 115 if (idx == -1) { 116 jobId = actionId; 117 } 118 else { 119 jobId = actionId.substring(0, idx); 120 } 121 setLogInfo(jobId, actionId); 122 log = XLog.getLog(getClass()); 123 log.debug("Received a CallbackServlet.doPost() with query string " + queryString); 124 125 validateContentType(request, RestConstants.TEXT_CONTENT_TYPE); 126 try { 127 log.info(XLog.STD, "callback for action [{0}]", actionId); 128 String data = IOUtils.getReaderAsString(request.getReader(), maxDataLen); 129 Properties props = PropertiesUtils.stringToProperties(data); 130 DagEngine dagEngine = Services.get().get(DagEngineService.class).getSystemDagEngine(); 131 dagEngine.processCallback(actionId, callbackService.getExternalStatus(queryString), props); 132 } 133 catch (IOException ex) { 134 if (ex.getMessage().startsWith("stream exceeds limit")) { 135 // TODO, WE MUST SET THE ACTION TO ERROR 136 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0403, "data too long"); 137 } 138 else { 139 throw ex; 140 } 141 } 142 catch (DagEngineException ex) { 143 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex); 144 } 145 } 146 }