001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 package org.apache.oozie.servlet; 019 020 import java.io.IOException; 021 import java.util.ArrayList; 022 import java.util.Arrays; 023 import java.util.HashMap; 024 import java.util.HashSet; 025 import java.util.List; 026 import java.util.Map; 027 import java.util.Set; 028 import java.util.StringTokenizer; 029 030 import javax.servlet.ServletException; 031 import javax.servlet.http.HttpServletRequest; 032 import javax.servlet.http.HttpServletResponse; 033 import org.apache.oozie.ErrorCode; 034 import org.apache.oozie.SLAEventBean; 035 import org.apache.oozie.client.OozieClient; 036 import org.apache.oozie.client.rest.RestConstants; 037 import org.apache.oozie.command.CommandException; 038 import org.apache.oozie.command.coord.SLAEventsXCommand; 039 import org.apache.oozie.util.XLog; 040 import org.apache.oozie.util.XmlUtils; 041 import org.jdom.Element; 042 043 @SuppressWarnings("deprecation") 044 public class SLAServlet extends JsonRestServlet { 045 046 private static final Set<String> SLA_FILTER_NAMES = new HashSet<String>(); 047 048 static { 049 SLA_FILTER_NAMES.add(OozieClient.FILTER_JOBID); 050 SLA_FILTER_NAMES.add(OozieClient.FILTER_APPNAME); 051 } 052 053 private static final String INSTRUMENTATION_NAME = "sla"; 054 055 private static final JsonRestServlet.ResourceInfo RESOURCES_INFO[] = new JsonRestServlet.ResourceInfo[1]; 056 057 static { 058 RESOURCES_INFO[0] = new JsonRestServlet.ResourceInfo("", Arrays.asList("GET"), Arrays.asList( 059 new JsonRestServlet.ParameterInfo(RestConstants.SLA_GT_SEQUENCE_ID, String.class, false, Arrays 060 .asList("GET")), new JsonRestServlet.ParameterInfo(RestConstants.MAX_EVENTS, String.class, 061 false, Arrays.asList("GET")), new JsonRestServlet.ParameterInfo( 062 RestConstants.JOBS_FILTER_PARAM, String.class, false, Arrays.asList("GET")))); 063 } 064 065 public SLAServlet() { 066 super(INSTRUMENTATION_NAME, RESOURCES_INFO); 067 } 068 069 public SLAServlet(String instrumentationName, ResourceInfo... resourcesInfo) { 070 super(instrumentationName, resourcesInfo); 071 } 072 073 /** 074 * Return information about SLA Events. 075 */ 076 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 077 078 Element eResponse = new Element("sla-message"); 079 List<SLAEventBean> slaEvntList = null; 080 081 try { 082 stopCron(); 083 String gtSequenceNum = request.getParameter(RestConstants.SLA_GT_SEQUENCE_ID); 084 String strMaxEvents = request.getParameter(RestConstants.MAX_EVENTS); 085 String filter = request.getParameter(RestConstants.JOBS_FILTER_PARAM); 086 Map<String, List<String>> filterList = parseFilter(filter, SLA_FILTER_NAMES); 087 088 int maxNoEvents = 100; // Default 089 XLog.getLog(getClass()).debug( 090 "Got SLA GET request for :" + gtSequenceNum + " and max-events :" + strMaxEvents); 091 if (strMaxEvents != null && strMaxEvents.length() > 0) { 092 maxNoEvents = Integer.parseInt(strMaxEvents); 093 } 094 095 if (gtSequenceNum != null) { 096 long seqId = Long.parseLong(gtSequenceNum); 097 stopCron(); 098 SLAEventsXCommand seCommand = new SLAEventsXCommand(seqId, maxNoEvents, filterList); 099 slaEvntList = seCommand.call(); 100 long lastSeqId = seCommand.getLastSeqId(); 101 102 eResponse = new Element("sla-message"); 103 for (SLAEventBean event : slaEvntList) { 104 eResponse.addContent(event.toXml()); 105 } 106 Element eLastSeq = new Element("last-sequence-id"); 107 eLastSeq.addContent(String.valueOf(lastSeqId)); 108 eResponse.addContent(eLastSeq); 109 XLog.getLog(getClass()).debug("Writing back SLA Servlet Caller with last-seq-id " + lastSeqId); 110 startCron(); 111 } 112 else { 113 XLog.getLog(getClass()).error("gt-sequence-id parameter is not specified in the http request"); 114 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0401, 115 "gt-sequence-id parameter is not specified in the http request"); 116 } 117 startCron(); 118 response.setContentType(XML_UTF8); 119 response.setStatus(HttpServletResponse.SC_OK); 120 response.getWriter().write(XmlUtils.prettyPrint(eResponse) + "\n"); 121 } 122 catch (CommandException ce) { 123 ce.printStackTrace(); 124 XLog.getLog(getClass()).error("Command exception ", ce); 125 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ce); 126 } 127 catch (RuntimeException re) { 128 re.printStackTrace(); 129 XLog.getLog(getClass()).error("Runtime error ", re); 130 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0307, re.getMessage()); 131 } 132 } 133 134 protected Map<String, List<String>> parseFilter(String filterString, Set<String> allowedFilters) throws ServletException { 135 Map<String, List<String>> map = new HashMap<String, List<String>>(); 136 if (filterString != null) { 137 StringTokenizer st = new StringTokenizer(filterString, ";"); 138 while (st.hasMoreTokens()) { 139 String token = st.nextToken(); 140 if (token.contains("=")) { 141 String[] pair = token.split("="); 142 if (pair.length != 2) { 143 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0401, 144 "elements must be name=value pairs"); 145 } 146 if (!allowedFilters.contains(pair[0])) { 147 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0401, 148 "invalid/unsupported names in filter"); 149 } 150 List<String> list = map.get(pair[0]); 151 if (list == null) { 152 list = new ArrayList<String>(); 153 map.put(pair[0], list); 154 } 155 list.add(pair[1]); 156 } 157 else { 158 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0401, 159 "elements must be name=value pairs"); 160 } 161 } 162 } 163 return map; 164 } 165 166 }