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    
020    import javax.servlet.ServletException;
021    import javax.servlet.http.HttpServletRequest;
022    import javax.servlet.http.HttpServletResponse;
023    
024    import org.apache.hadoop.conf.Configuration;
025    import org.apache.oozie.ErrorCode;
026    import org.apache.oozie.client.OozieClient;
027    import org.apache.oozie.client.rest.RestConstants;
028    import org.apache.oozie.service.Services;
029    import org.apache.oozie.service.WorkflowAppService;
030    import org.apache.oozie.util.XConfiguration;
031    import org.json.simple.JSONObject;
032    
033    public abstract class BaseJobsServlet extends JsonRestServlet {
034    
035        private static final JsonRestServlet.ResourceInfo RESOURCES_INFO[] = new JsonRestServlet.ResourceInfo[1];
036    
037        static {
038            RESOURCES_INFO[0] = new JsonRestServlet.ResourceInfo("", Arrays.asList(
039                    "POST", "GET"), Arrays.asList(
040                    new JsonRestServlet.ParameterInfo(RestConstants.ACTION_PARAM,
041                                                      String.class, false, Arrays.asList("POST")),
042                    new JsonRestServlet.ParameterInfo(
043                            RestConstants.JOBS_FILTER_PARAM, String.class, false,
044                            Arrays.asList("GET")),
045                    new JsonRestServlet.ParameterInfo(RestConstants.JOBTYPE_PARAM,
046                                                      String.class, false, Arrays.asList("GET", "POST")),
047                    new JsonRestServlet.ParameterInfo(RestConstants.OFFSET_PARAM,
048                                                      String.class, false, Arrays.asList("GET")),
049                    new JsonRestServlet.ParameterInfo(RestConstants.LEN_PARAM,
050                                                      String.class, false, Arrays.asList("GET")),
051    
052                    new JsonRestServlet.ParameterInfo(
053                            RestConstants.JOBS_EXTERNAL_ID_PARAM, String.class,
054                            false, Arrays.asList("GET"))));
055        }
056    
057        public BaseJobsServlet(String instrumentationName) {
058            super(instrumentationName, RESOURCES_INFO);
059        }
060    
061        /**
062         * Create a job.
063         */
064        @Override
065        @SuppressWarnings("unchecked")
066        protected void doPost(HttpServletRequest request,
067                HttpServletResponse response) throws ServletException, IOException {
068            String authTok = getAuthToken(request);
069            /*
070             * Enumeration p = request.getAttributeNames();
071             * for(;p.hasMoreElements();){ String key = (String)p.nextElement();
072             * XLog.getLog(getClass()).warn(" key "+ key + " val "+ (String)
073             * request.getAttribute(key)); }
074             */
075            validateContentType(request, RestConstants.XML_CONTENT_TYPE);
076    
077            request.setAttribute(AUDIT_OPERATION, request
078                    .getParameter(RestConstants.ACTION_PARAM));
079    
080            XConfiguration conf = new XConfiguration(request.getInputStream());
081    
082            stopCron();
083    
084            conf = conf.trim();        
085            conf = conf.resolve();
086    
087            validateJobConfiguration(conf);
088            BaseJobServlet.checkAuthorizationForApp(getUser(request), conf);
089    
090            JSONObject json = submitJob(request, conf);
091            startCron();
092            sendJsonResponse(response, HttpServletResponse.SC_CREATED, json);
093        }
094    
095        /**
096         * Return information about jobs.
097         */
098        @Override
099        @SuppressWarnings("unchecked")
100        public void doGet(HttpServletRequest request, HttpServletResponse response)
101        throws ServletException, IOException {
102            String externalId = request
103            .getParameter(RestConstants.JOBS_EXTERNAL_ID_PARAM);
104            if (externalId != null) {
105                stopCron();
106                JSONObject json = getJobIdForExternalId(request, externalId);
107                startCron();
108                sendJsonResponse(response, HttpServletResponse.SC_OK, json);
109            }
110            else {
111                stopCron();
112                // Configuration conf = new
113                // XConfiguration(request.getInputStream());
114                JSONObject json = getJobs(request);
115                startCron();
116                sendJsonResponse(response, HttpServletResponse.SC_OK, json);
117            }
118        }
119    
120        /**
121         * abstract method to submit a job, either workflow or coordinator in the case of workflow job, there is an optional
122         * flag in request to indicate if want this job to be started immediately or not
123         *
124         * @param request
125         * @param conf
126         * @return JSONObject of job id
127         * @throws XServletException
128         * @throws IOException
129         */
130        abstract JSONObject submitJob(HttpServletRequest request, Configuration conf)
131        throws XServletException, IOException;
132    
133        /**
134         * abstract method to get a job from external ID
135         *
136         * @param request
137         * @param externalId
138         * @return JSONObject for the requested job
139         * @throws XServletException
140         * @throws IOException
141         */
142        abstract JSONObject getJobIdForExternalId(HttpServletRequest request,
143                String externalId) throws XServletException, IOException;
144    
145        /**
146         * abstract method to get a list of workflow jobs
147         *
148         * @param request
149         * @return JSONObject of the requested jobs
150         * @throws XServletException
151         * @throws IOException
152         */
153        abstract JSONObject getJobs(HttpServletRequest request)
154        throws XServletException, IOException;
155    
156        static void validateJobConfiguration(Configuration conf) throws XServletException {
157            if (conf.get(OozieClient.USER_NAME) == null) {
158                throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0401,
159                        OozieClient.USER_NAME);
160            }
161    
162            String localRealm = Services.get().getConf().get("local.realm");
163    
164            //if the job properties don't define JT/NN Kerberos principals, add default value
165            if (conf.get(WorkflowAppService.HADOOP_JT_KERBEROS_NAME) == null) {
166                conf.set(WorkflowAppService.HADOOP_JT_KERBEROS_NAME, "mapred/_HOST@" + localRealm);
167            }
168            if (conf.get(WorkflowAppService.HADOOP_NN_KERBEROS_NAME) == null) {
169                conf.set(WorkflowAppService.HADOOP_NN_KERBEROS_NAME, "hdfs/_HOST@" + localRealm);
170            }
171        }
172    }