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
019package org.apache.oozie.servlet;
020
021import java.io.IOException;
022import java.util.ArrayList;
023import java.util.List;
024
025import javax.servlet.http.HttpServletRequest;
026import javax.servlet.http.HttpServletResponse;
027
028import org.apache.commons.lang.StringUtils;
029import org.apache.hadoop.conf.Configuration;
030import org.apache.oozie.BaseEngineException;
031import org.apache.oozie.BundleEngine;
032import org.apache.oozie.CoordinatorActionBean;
033import org.apache.oozie.CoordinatorActionInfo;
034import org.apache.oozie.CoordinatorEngine;
035import org.apache.oozie.CoordinatorEngineException;
036import org.apache.oozie.DagEngine;
037import org.apache.oozie.DagEngineException;
038import org.apache.oozie.ErrorCode;
039import org.apache.oozie.client.CoordinatorAction;
040import org.apache.oozie.client.rest.JsonBean;
041import org.apache.oozie.client.rest.JsonTags;
042import org.apache.oozie.client.rest.RestConstants;
043import org.apache.oozie.command.CommandException;
044import org.apache.oozie.service.BundleEngineService;
045import org.apache.oozie.service.CoordinatorEngineService;
046import org.apache.oozie.service.DagEngineService;
047import org.apache.oozie.service.Services;
048import org.json.simple.JSONObject;
049
050@SuppressWarnings("serial")
051public class V2JobServlet extends V1JobServlet {
052
053    private static final String INSTRUMENTATION_NAME = "v2job";
054
055    public V2JobServlet() {
056        super(INSTRUMENTATION_NAME);
057    }
058
059    @Override
060    protected JsonBean getWorkflowJob(HttpServletRequest request, HttpServletResponse response) throws XServletException {
061        JsonBean jobBean = super.getWorkflowJobBean(request, response);
062        return jobBean;
063    }
064
065    @Override
066    protected JsonBean getWorkflowAction(HttpServletRequest request, HttpServletResponse response) throws XServletException {
067        JsonBean actionBean = super.getWorkflowActionBean(request, response);
068        return actionBean;
069    }
070
071    @Override
072    protected int getCoordinatorJobLength(int defaultLen, int len) {
073        return (len < 0) ? defaultLen : len;
074    }
075
076    @Override
077    protected String getJMSTopicName(HttpServletRequest request, HttpServletResponse response) throws XServletException,
078            IOException {
079        String topicName;
080        String jobId = getResourceName(request);
081        DagEngine dagEngine = Services.get().get(DagEngineService.class).getDagEngine(getUser(request));
082        try {
083            topicName = dagEngine.getJMSTopicName(jobId);
084        }
085        catch (DagEngineException ex) {
086            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
087        }
088        return topicName;
089    }
090
091    @Override
092    protected JSONObject getJobsByParentId(HttpServletRequest request, HttpServletResponse response)
093            throws XServletException, IOException {
094        return super.getJobsByParentId(request, response);
095    }
096
097    /**
098     * Update coord job.
099     *
100     * @param request the request
101     * @param response the response
102     * @return the JSON object
103     * @throws XServletException the x servlet exception
104     * @throws IOException Signals that an I/O exception has occurred.
105     */
106    @SuppressWarnings("unchecked")
107    @Override
108    protected JSONObject updateJob(HttpServletRequest request, HttpServletResponse response, Configuration conf)
109            throws XServletException, IOException {
110        CoordinatorEngine coordEngine = Services.get().get(CoordinatorEngineService.class)
111                .getCoordinatorEngine(getUser(request));
112        JSONObject json = new JSONObject();
113        try {
114            String jobId = getResourceName(request);
115            boolean dryrun = StringUtils.isEmpty(request.getParameter(RestConstants.JOB_ACTION_DRYRUN)) ? false
116                    : Boolean.parseBoolean(request.getParameter(RestConstants.JOB_ACTION_DRYRUN));
117            boolean showDiff = StringUtils.isEmpty(request.getParameter(RestConstants.JOB_ACTION_SHOWDIFF)) ? true
118                    : Boolean.parseBoolean(request.getParameter(RestConstants.JOB_ACTION_SHOWDIFF));
119
120            String diff = coordEngine.updateJob(conf, jobId, dryrun, showDiff);
121            JSONObject diffJson = new JSONObject();
122            diffJson.put(JsonTags.COORD_UPDATE_DIFF, diff);
123            json.put(JsonTags.COORD_UPDATE, diffJson);
124        }
125        catch (CoordinatorEngineException e) {
126            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, e);
127        }
128        return json;
129    }
130
131    /**
132     * Ignore a coordinator job
133     * @param request request object
134     * @param response response object
135     * @throws XServletException
136     * @throws IOException
137     */
138    @Override
139    protected JSONObject ignoreJob(HttpServletRequest request, HttpServletResponse response) throws XServletException, IOException {
140        String jobId = getResourceName(request);
141        if (jobId.endsWith("-W")) {
142            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0302, "Workflow Ignore Not supported");
143        } else if (jobId.endsWith("-B")) {
144            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0302, "Bundle Ignore Not supported");
145        } else {
146            return ignoreCoordinatorJob(request, response);
147        }
148
149    }
150
151    /**
152     * Ignore a coordinator job/action
153     *
154     * @param request servlet request
155     * @param response servlet response
156     * @throws XServletException
157     */
158    @SuppressWarnings("unchecked")
159    private JSONObject ignoreCoordinatorJob(HttpServletRequest request, HttpServletResponse response)
160            throws XServletException {
161        JSONObject json = null;
162        CoordinatorEngine coordEngine = Services.get().get(CoordinatorEngineService.class).getCoordinatorEngine(
163                getUser(request));
164        String jobId = getResourceName(request);
165        String type = request.getParameter(RestConstants.JOB_COORD_RANGE_TYPE_PARAM);
166        String scope = request.getParameter(RestConstants.JOB_COORD_SCOPE_PARAM);
167        String changeValue = "status=" + CoordinatorAction.Status.IGNORED;
168        List<CoordinatorActionBean> coordActions = new ArrayList<CoordinatorActionBean>();
169        try {
170            if (type != null && !type.equals(RestConstants.JOB_COORD_SCOPE_ACTION)) {
171                throw new CommandException(ErrorCode.E1024, "Currently ignore only support -action option");
172            }
173            CoordinatorActionInfo coordInfo = null;
174            if(scope == null || scope.isEmpty()) {
175                coordEngine.change(jobId, changeValue);
176            } else{
177                coordInfo = coordEngine.ignore(jobId, type, scope);
178            }
179            if(coordInfo != null) {
180                coordActions = coordInfo.getCoordActions();
181                json = new JSONObject();
182                json.put(JsonTags.COORDINATOR_ACTIONS, CoordinatorActionBean.toJSONArray(coordActions, "GMT"));
183            }
184            return json;
185        }
186        catch (CommandException ex) {
187            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
188        }
189        catch (CoordinatorEngineException ex) {
190            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
191        }
192    }
193
194    @Override
195    @SuppressWarnings("unchecked")
196    protected String getJobStatus(HttpServletRequest request, HttpServletResponse response) throws XServletException,
197            IOException {
198        String status;
199        String jobId = getResourceName(request);
200        try {
201            if (jobId.endsWith("-B")) {
202                BundleEngine engine = Services.get().get(BundleEngineService.class).getBundleEngine(getUser(request));
203                status = engine.getJobStatus(jobId);
204            } else if (jobId.endsWith("-W")) {
205                DagEngine engine = Services.get().get(DagEngineService.class).getDagEngine(getUser(request));
206                status = engine.getJobStatus(jobId);
207            } else {
208                CoordinatorEngine engine =
209                        Services.get().get(CoordinatorEngineService.class).getCoordinatorEngine(getUser(request));
210                if (jobId.contains("-C@")) {
211                    status = engine.getActionStatus(jobId);
212                } else {
213                    status = engine.getJobStatus(jobId);
214                }
215            }
216        } catch (BaseEngineException ex) {
217            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
218        }
219        return status;
220    }
221}