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 public class SLAServlet extends JsonRestServlet { 044 045 private static final Set<String> SLA_FILTER_NAMES = new HashSet<String>(); 046 047 static { 048 SLA_FILTER_NAMES.add(OozieClient.FILTER_JOBID); 049 SLA_FILTER_NAMES.add(OozieClient.FILTER_APPNAME); 050 } 051 052 private static final String INSTRUMENTATION_NAME = "sla"; 053 054 private static final JsonRestServlet.ResourceInfo RESOURCES_INFO[] = new JsonRestServlet.ResourceInfo[1]; 055 056 static { 057 RESOURCES_INFO[0] = new JsonRestServlet.ResourceInfo("", Arrays.asList("GET"), Arrays.asList( 058 new JsonRestServlet.ParameterInfo(RestConstants.SLA_GT_SEQUENCE_ID, String.class, false, Arrays 059 .asList("GET")), new JsonRestServlet.ParameterInfo(RestConstants.MAX_EVENTS, String.class, 060 false, Arrays.asList("GET")), new JsonRestServlet.ParameterInfo( 061 RestConstants.JOBS_FILTER_PARAM, String.class, false, Arrays.asList("GET")))); 062 } 063 064 public SLAServlet() { 065 super(INSTRUMENTATION_NAME, RESOURCES_INFO); 066 } 067 068 /** 069 * Return information about SLA Events. 070 */ 071 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 072 073 Element eResponse = new Element("sla-message"); 074 List<SLAEventBean> slaEvntList = null; 075 076 try { 077 stopCron(); 078 String gtSequenceNum = request.getParameter(RestConstants.SLA_GT_SEQUENCE_ID); 079 String strMaxEvents = request.getParameter(RestConstants.MAX_EVENTS); 080 String filter = request.getParameter(RestConstants.JOBS_FILTER_PARAM); 081 Map<String, List<String>> filterList = parseFilter(filter); 082 083 int maxNoEvents = 100; // Default 084 XLog.getLog(getClass()).debug( 085 "Got SLA GET request for :" + gtSequenceNum + " and max-events :" + strMaxEvents); 086 if (strMaxEvents != null && strMaxEvents.length() > 0) { 087 maxNoEvents = Integer.parseInt(strMaxEvents); 088 } 089 090 if (gtSequenceNum != null) { 091 long seqId = Long.parseLong(gtSequenceNum); 092 stopCron(); 093 SLAEventsXCommand seCommand = new SLAEventsXCommand(seqId, maxNoEvents, filterList); 094 slaEvntList = seCommand.call(); 095 long lastSeqId = seCommand.getLastSeqId(); 096 097 eResponse = new Element("sla-message"); 098 for (SLAEventBean event : slaEvntList) { 099 eResponse.addContent(event.toXml()); 100 } 101 Element eLastSeq = new Element("last-sequence-id"); 102 eLastSeq.addContent(String.valueOf(lastSeqId)); 103 eResponse.addContent(eLastSeq); 104 XLog.getLog(getClass()).debug("Writing back SLA Servlet Caller with last-seq-id " + lastSeqId); 105 startCron(); 106 } 107 else { 108 XLog.getLog(getClass()).error("gt-sequence-id parameter is not specified in the http request"); 109 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0401, 110 "gt-sequence-id parameter is not specified in the http request"); 111 } 112 startCron(); 113 response.setContentType(XML_UTF8); 114 response.setStatus(HttpServletResponse.SC_OK); 115 response.getWriter().write(XmlUtils.prettyPrint(eResponse) + "\n"); 116 } 117 catch (CommandException ce) { 118 ce.printStackTrace(); 119 XLog.getLog(getClass()).error("Command exception ", ce); 120 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ce); 121 } 122 catch (RuntimeException re) { 123 re.printStackTrace(); 124 XLog.getLog(getClass()).error("Runtime error ", re); 125 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0307, re.getMessage()); 126 } 127 } 128 129 protected Map<String, List<String>> parseFilter(String filter) throws ServletException { 130 Map<String, List<String>> map = new HashMap<String, List<String>>(); 131 if (filter != null) { 132 StringTokenizer st = new StringTokenizer(filter, ";"); 133 while (st.hasMoreTokens()) { 134 String token = st.nextToken(); 135 if (token.contains("=")) { 136 String[] pair = token.split("="); 137 if (pair.length != 2) { 138 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0401, 139 "elements must be name=value pairs"); 140 } 141 if (!SLA_FILTER_NAMES.contains(pair[0])) { 142 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0401, 143 "invalid/unsupported names in filter"); 144 } 145 List<String> list = map.get(pair[0]); 146 if (list == null) { 147 list = new ArrayList<String>(); 148 map.put(pair[0], list); 149 } 150 list.add(pair[1]); 151 } 152 else { 153 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0401, 154 "elements must be name=value pairs"); 155 } 156 } 157 } 158 return map; 159 } 160 161 }