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.List;
023import java.util.Locale;
024
025import javax.servlet.ServletInputStream;
026import javax.servlet.http.HttpServletRequest;
027import javax.servlet.http.HttpServletResponse;
028
029import com.google.common.base.Strings;
030import org.apache.hadoop.conf.Configuration;
031import org.apache.oozie.*;
032import org.apache.oozie.client.WorkflowAction;
033import org.apache.oozie.client.WorkflowJob;
034import org.apache.oozie.client.rest.*;
035import org.apache.oozie.command.CommandException;
036import org.apache.oozie.coord.CoordUtils;
037import org.apache.oozie.service.BundleEngineService;
038import org.apache.oozie.service.ConfigurationService;
039import org.apache.oozie.service.CoordinatorEngineService;
040import org.apache.oozie.service.DagEngineService;
041import org.apache.oozie.service.Services;
042import org.apache.oozie.service.UUIDService;
043import org.apache.oozie.util.Instrumentation;
044import org.apache.oozie.util.graph.GraphGenerator;
045import org.apache.oozie.util.XLog;
046import org.apache.oozie.util.graph.GraphRenderer;
047import org.apache.oozie.util.graph.GraphvizRenderer;
048import org.apache.oozie.util.graph.OutputFormat;
049import org.json.simple.JSONArray;
050import org.json.simple.JSONObject;
051
052
053@SuppressWarnings("serial")
054public class V1JobServlet extends BaseJobServlet {
055
056    private static final String INSTRUMENTATION_NAME = "v1job";
057    public static final String COORD_ACTIONS_DEFAULT_LENGTH = "oozie.coord.actions.default.length";
058
059    final static String NOT_SUPPORTED_MESSAGE = "Not supported in v1";
060
061
062    public V1JobServlet() {
063        super(INSTRUMENTATION_NAME);
064    }
065
066    protected V1JobServlet(String instrumentation_name){
067        super(instrumentation_name);
068    }
069
070    /*
071     * protected method to start a job
072     */
073    @Override
074    protected void startJob(HttpServletRequest request, HttpServletResponse response) throws XServletException,
075            IOException {
076        /*
077         * Configuration conf = new XConfiguration(request.getInputStream());
078         * String wfPath = conf.get(OozieClient.APP_PATH); String coordPath =
079         * conf.get(OozieClient.COORDINATOR_APP_PATH);
080         *
081         * ServletUtilities.ValidateAppPath(wfPath, coordPath);
082         */
083        String jobId = getResourceName(request);
084        if (jobId.endsWith("-W")) {
085            startWorkflowJob(request, response);
086        }
087        else if (jobId.endsWith("-B")) {
088            startBundleJob(request, response);
089        }
090        else {
091            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0303, RestConstants.ACTION_PARAM,
092                    RestConstants.JOB_ACTION_START);
093        }
094
095    }
096
097    /*
098     * protected method to resume a job
099     */
100    @Override
101    protected void resumeJob(HttpServletRequest request, HttpServletResponse response) throws XServletException,
102            IOException {
103        /*
104         * Configuration conf = new XConfiguration(request.getInputStream());
105         * String wfPath = conf.get(OozieClient.APP_PATH); String coordPath =
106         * conf.get(OozieClient.COORDINATOR_APP_PATH);
107         *
108         * ServletUtilities.ValidateAppPath(wfPath, coordPath);
109         */
110        String jobId = getResourceName(request);
111        if (jobId.endsWith("-W")) {
112            resumeWorkflowJob(request, response);
113        }
114        else if (jobId.endsWith("-B")) {
115            resumeBundleJob(request, response);
116        }
117        else {
118            resumeCoordinatorJob(request, response);
119        }
120    }
121
122    /*
123     * protected method to suspend a job
124     */
125    @Override
126    protected void suspendJob(HttpServletRequest request, HttpServletResponse response) throws XServletException,
127            IOException {
128        /*
129         * Configuration conf = new XConfiguration(request.getInputStream());
130         * String wfPath = conf.get(OozieClient.APP_PATH); String coordPath =
131         * conf.get(OozieClient.COORDINATOR_APP_PATH);
132         *
133         * ServletUtilities.ValidateAppPath(wfPath, coordPath);
134         */
135        String jobId = getResourceName(request);
136        if (jobId.endsWith("-W")) {
137            suspendWorkflowJob(request, response);
138        }
139        else if (jobId.endsWith("-B")) {
140            suspendBundleJob(request, response);
141        }
142        else {
143            suspendCoordinatorJob(request, response);
144        }
145    }
146
147    /*
148     * protected method to kill a job
149     */
150    @Override
151    protected JSONObject killJob(HttpServletRequest request, HttpServletResponse response) throws XServletException,
152            IOException {
153        /*
154         * Configuration conf = new XConfiguration(request.getInputStream());
155         * String wfPath = conf.get(OozieClient.APP_PATH); String coordPath =
156         * conf.get(OozieClient.COORDINATOR_APP_PATH);
157         *
158         * ServletUtilities.ValidateAppPath(wfPath, coordPath);
159         */
160        String jobId = getResourceName(request);
161        JSONObject json = null;
162        if (jobId.endsWith("-W")) {
163            killWorkflowJob(request, response);
164        }
165        else if (jobId.endsWith("-B")) {
166            killBundleJob(request, response);
167        }
168        else {
169            json = killCoordinator(request, response);
170        }
171        return json;
172    }
173
174    /**
175     * protected method to change a coordinator job
176     * @param request request object
177     * @param response response object
178     * @throws XServletException
179     * @throws IOException
180     */
181    @Override
182    protected void changeJob(HttpServletRequest request, HttpServletResponse response) throws XServletException,
183            IOException {
184        String jobId = getResourceName(request);
185        if (jobId.endsWith("-B")) {
186            changeBundleJob(request, response);
187        }
188        else {
189            changeCoordinatorJob(request, response);
190        }
191    }
192    @Override
193    protected JSONObject ignoreJob(HttpServletRequest request, HttpServletResponse response) throws XServletException, IOException {
194        throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0302, NOT_SUPPORTED_MESSAGE);
195    }
196
197    /*
198     * protected method to reRun a job
199     *
200     * @seeorg.apache.oozie.servlet.BaseJobServlet#reRunJob(javax.servlet.http.
201     * HttpServletRequest, javax.servlet.http.HttpServletResponse,
202     * org.apache.hadoop.conf.Configuration)
203     */
204    @Override
205    protected JSONObject reRunJob(HttpServletRequest request, HttpServletResponse response, Configuration conf)
206            throws XServletException, IOException {
207        JSONObject json = null;
208        String jobId = getResourceName(request);
209        if (jobId.endsWith("-W")) {
210            reRunWorkflowJob(request, response, conf);
211        }
212        else if (jobId.endsWith("-B")) {
213            rerunBundleJob(request, response, conf);
214        }
215        else {
216            json = reRunCoordinatorActions(request, response, conf);
217        }
218        return json;
219    }
220
221    /*
222     * protected method to get a job in JsonBean representation
223     */
224    @Override
225    protected JsonBean getJob(HttpServletRequest request, HttpServletResponse response) throws XServletException,
226            IOException, BaseEngineException {
227        ServletInputStream is = request.getInputStream();
228        byte[] b = new byte[101];
229        while (is.readLine(b, 0, 100) != -1) {
230            XLog.getLog(getClass()).warn("Printing :" + new String(b));
231        }
232
233        JsonBean jobBean = null;
234        String jobId = getResourceName(request);
235        if (jobId.endsWith("-B")) {
236            jobBean = getBundleJob(request, response);
237        }
238        else {
239            if (jobId.endsWith("-W")) {
240                jobBean = getWorkflowJob(request, response);
241            }
242            else {
243                if (jobId.contains("-W@")) {
244                    jobBean = getWorkflowAction(request, response);
245                }
246                else {
247                    if (jobId.contains("-C@")) {
248                        jobBean = getCoordinatorAction(request, response);
249                    }
250                    else {
251                        jobBean = getCoordinatorJob(request, response);
252                    }
253                }
254            }
255        }
256
257        return jobBean;
258    }
259
260    /*
261     * protected method to get a job definition in String format
262     */
263    @Override
264    protected String getJobDefinition(HttpServletRequest request, HttpServletResponse response)
265            throws XServletException, IOException {
266        String jobDefinition = null;
267        String jobId = getResourceName(request);
268        if (jobId.endsWith("-W")) {
269            jobDefinition = getWorkflowJobDefinition(request, response);
270        }
271        else if (jobId.endsWith("-B")) {
272            jobDefinition = getBundleJobDefinition(request, response);
273        }
274        else {
275            jobDefinition = getCoordinatorJobDefinition(request, response);
276        }
277        return jobDefinition;
278    }
279
280    /*
281     * protected method to stream a job log into response object
282     */
283    @Override
284    protected void streamJobLog(HttpServletRequest request, HttpServletResponse response) throws XServletException,
285            IOException {
286        try {
287            String jobId = getResourceName(request);
288            if (jobId.endsWith("-W")) {
289                streamWorkflowJobLog(request, response);
290            }
291            else if (jobId.endsWith("-B")) {
292                streamBundleJobLog(request, response);
293            }
294            else {
295                streamCoordinatorJobLog(request, response);
296            }
297        }
298        catch (Exception e) {
299            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0307, e.getMessage());
300        }
301    }
302
303    @Override
304    protected void streamJobGraph(HttpServletRequest request, HttpServletResponse response)
305            throws XServletException, IOException {
306        String jobId = getResourceName(request);
307        if (jobId.endsWith("-W")) {
308            try {
309
310                final String showKillParameter = request.getParameter(RestConstants.JOB_SHOW_KILL_PARAM);
311                final boolean showKill = isShowKillSet(showKillParameter);
312
313                final String formatParameter = request.getParameter(RestConstants.JOB_FORMAT_PARAM);
314                final OutputFormat outputFormat = getOutputFormat(formatParameter);
315
316                final String contentType = getContentType(outputFormat);
317
318                response.setContentType(contentType);
319
320                final Instrumentation.Cron cron = new Instrumentation.Cron();
321                cron.start();
322
323                final GraphRenderer graphRenderer = new GraphvizRenderer();
324
325                new GraphGenerator(
326                            getWorkflowJobDefinition(request, response),
327                            (WorkflowJobBean)getWorkflowJob(request, response),
328                            showKill,
329                            graphRenderer).write(response.getOutputStream(), outputFormat);
330
331                cron.stop();
332                instrument(outputFormat, cron);
333            }
334            catch (final Exception e) {
335                throw new XServletException(HttpServletResponse.SC_NOT_FOUND, ErrorCode.E0307, e.getMessage(), e);
336            }
337        }
338        else {
339            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0306);
340        }
341    }
342
343    private boolean isShowKillSet(final String showKillParameter) {
344        return showKillParameter != null &&
345                (showKillParameter.equalsIgnoreCase("yes") ||
346                        showKillParameter.equals("1") ||
347                        showKillParameter.equalsIgnoreCase("true"));
348    }
349
350    private OutputFormat getOutputFormat(final String formatParameter) {
351        final OutputFormat outputFormat;
352        if (Strings.isNullOrEmpty(formatParameter)) {
353            outputFormat = OutputFormat.PNG;
354        }
355        else {
356            outputFormat = OutputFormat.valueOf(formatParameter.toUpperCase(Locale.getDefault()));
357        }
358        return outputFormat;
359    }
360
361    private String getContentType(final OutputFormat outputFormat) {
362        final String contentType;
363
364        switch (outputFormat) {
365            case PNG:
366                contentType = RestConstants.PNG_IMAGE_CONTENT_TYPE;
367                break;
368            case DOT:
369                contentType = RestConstants.TEXT_CONTENT_TYPE;
370                break;
371            case SVG:
372                contentType = RestConstants.SVG_IMAGE_CONTENT_TYPE;
373                break;
374            default:
375                throw new IllegalArgumentException("Unknown output format, cannot get content type: " + outputFormat);
376        }
377
378        return contentType;
379    }
380
381    private void instrument(final OutputFormat outputFormat, final Instrumentation.Cron cron) {
382        addCron(INSTRUMENTATION_NAME + "-graph", cron);
383        incrCounter(INSTRUMENTATION_NAME + "-graph", 1);
384        addCron(INSTRUMENTATION_NAME + "-graph-" + outputFormat.toString().toLowerCase(Locale.getDefault()), cron);
385        incrCounter(INSTRUMENTATION_NAME + "-graph-" + outputFormat.toString().toLowerCase(Locale.getDefault()), 1);
386    }
387
388    /**
389     * Start wf job
390     *
391     * @param request servlet request
392     * @param response servlet response
393     * @throws XServletException
394     */
395    private void startWorkflowJob(HttpServletRequest request, HttpServletResponse response) throws XServletException {
396        DagEngine dagEngine = Services.get().get(DagEngineService.class).getDagEngine(getUser(request));
397
398        String jobId = getResourceName(request);
399        try {
400            dagEngine.start(jobId);
401        }
402        catch (DagEngineException ex) {
403            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
404        }
405    }
406
407    /**
408     * Start bundle job
409     *
410     * @param request servlet request
411     * @param response servlet response
412     * @throws XServletException
413     */
414    private void startBundleJob(HttpServletRequest request, HttpServletResponse response) throws XServletException {
415        BundleEngine bundleEngine = Services.get().get(BundleEngineService.class).getBundleEngine(getUser(request));
416        String jobId = getResourceName(request);
417        try {
418            bundleEngine.start(jobId);
419        }
420        catch (BundleEngineException ex) {
421            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
422        }
423    }
424
425    /**
426     * Resume workflow job
427     *
428     * @param request servlet request
429     * @param response servlet response
430     * @throws XServletException
431     */
432    private void resumeWorkflowJob(HttpServletRequest request, HttpServletResponse response) throws XServletException {
433        DagEngine dagEngine = Services.get().get(DagEngineService.class).getDagEngine(getUser(request));
434
435        String jobId = getResourceName(request);
436        try {
437            dagEngine.resume(jobId);
438        }
439        catch (DagEngineException ex) {
440            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
441        }
442    }
443
444    /**
445     * Resume bundle job
446     *
447     * @param request servlet request
448     * @param response servlet response
449     * @throws XServletException
450     */
451    private void resumeBundleJob(HttpServletRequest request, HttpServletResponse response) throws XServletException {
452        BundleEngine bundleEngine = Services.get().get(BundleEngineService.class).getBundleEngine(getUser(request));
453        String jobId = getResourceName(request);
454        try {
455            bundleEngine.resume(jobId);
456        }
457        catch (BundleEngineException ex) {
458            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
459        }
460    }
461
462    /**
463     * Resume coordinator job
464     *
465     * @param request servlet request
466     * @param response servlet response
467     * @throws XServletException
468     * @throws CoordinatorEngineException
469     */
470    private void resumeCoordinatorJob(HttpServletRequest request, HttpServletResponse response)
471            throws XServletException {
472        String jobId = getResourceName(request);
473        CoordinatorEngine coordEngine = Services.get().get(CoordinatorEngineService.class).getCoordinatorEngine(
474                getUser(request));
475        try {
476            coordEngine.resume(jobId);
477        }
478        catch (CoordinatorEngineException ex) {
479            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
480        }
481    }
482
483    /**
484     * Suspend a wf job
485     *
486     * @param request servlet request
487     * @param response servlet response
488     * @throws XServletException
489     */
490    private void suspendWorkflowJob(HttpServletRequest request, HttpServletResponse response) throws XServletException {
491        DagEngine dagEngine = Services.get().get(DagEngineService.class).getDagEngine(getUser(request));
492
493        String jobId = getResourceName(request);
494        try {
495            dagEngine.suspend(jobId);
496        }
497        catch (DagEngineException ex) {
498            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
499        }
500    }
501
502    /**
503     * Suspend bundle job
504     *
505     * @param request servlet request
506     * @param response servlet response
507     * @throws XServletException
508     */
509    private void suspendBundleJob(HttpServletRequest request, HttpServletResponse response) throws XServletException {
510        BundleEngine bundleEngine = Services.get().get(BundleEngineService.class).getBundleEngine(getUser(request));
511        String jobId = getResourceName(request);
512        try {
513            bundleEngine.suspend(jobId);
514        }
515        catch (BundleEngineException ex) {
516            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
517        }
518    }
519
520    /**
521     * Suspend coordinator job
522     *
523     * @param request servlet request
524     * @param response servlet response
525     * @throws XServletException
526     */
527    private void suspendCoordinatorJob(HttpServletRequest request, HttpServletResponse response)
528            throws XServletException {
529        CoordinatorEngine coordEngine = Services.get().get(CoordinatorEngineService.class).getCoordinatorEngine(
530                getUser(request));
531        String jobId = getResourceName(request);
532        try {
533            coordEngine.suspend(jobId);
534        }
535        catch (CoordinatorEngineException ex) {
536            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
537        }
538    }
539
540    /**
541     * Kill a wf job
542     * @param request servlet request
543     * @param response servlet response
544     * @throws XServletException
545     */
546    private void killWorkflowJob(HttpServletRequest request, HttpServletResponse response) throws XServletException {
547        DagEngine dagEngine = Services.get().get(DagEngineService.class).getDagEngine(getUser(request));
548
549        String jobId = getResourceName(request);
550        try {
551            dagEngine.kill(jobId);
552        }
553        catch (DagEngineException ex) {
554            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
555        }
556    }
557
558    /**
559     * Kill a coord job
560     *
561     * @param request servlet request
562     * @param response servlet response
563     * @throws XServletException
564     */
565    @SuppressWarnings("unchecked")
566    private JSONObject killCoordinator(HttpServletRequest request, HttpServletResponse response) throws XServletException {
567        String jobId = getResourceName(request);
568        CoordinatorEngine coordEngine = Services.get().get(CoordinatorEngineService.class)
569                .getCoordinatorEngine(getUser(request));
570        JSONObject json = null;
571        String rangeType = request.getParameter(RestConstants.JOB_COORD_RANGE_TYPE_PARAM);
572        String scope = request.getParameter(RestConstants.JOB_COORD_SCOPE_PARAM);
573
574        try {
575            if (rangeType != null && scope != null) {
576                XLog.getLog(getClass()).info(
577                        "Kill coordinator actions for jobId=" + jobId + ", rangeType=" + rangeType + ",scope=" + scope);
578
579                json = new JSONObject();
580                CoordinatorActionInfo coordInfo = coordEngine.killActions(jobId, rangeType, scope);
581                List<CoordinatorActionBean> coordActions;
582                if (coordInfo != null) {
583                    coordActions = coordInfo.getCoordActions();
584                }
585                else {
586                    coordActions = CoordUtils.getCoordActions(rangeType, jobId, scope, true);
587                }
588                json.put(JsonTags.COORDINATOR_ACTIONS, CoordinatorActionBean.toJSONArray(coordActions, "GMT"));
589            }
590            else {
591                coordEngine.kill(jobId);
592            }
593        }
594        catch (CoordinatorEngineException ex) {
595            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
596        }
597        catch (CommandException ex) {
598            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
599        }
600        return json;
601    }
602
603    /**
604     * Kill bundle job
605     *
606     * @param request servlet request
607     * @param response servlet response
608     * @throws XServletException
609     */
610    private void killBundleJob(HttpServletRequest request, HttpServletResponse response) throws XServletException {
611        BundleEngine bundleEngine = Services.get().get(BundleEngineService.class).getBundleEngine(getUser(request));
612        String jobId = getResourceName(request);
613        try {
614            bundleEngine.kill(jobId);
615        }
616        catch (BundleEngineException ex) {
617            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
618        }
619    }
620
621    /**
622     * Change a coordinator job
623     *
624     * @param request servlet request
625     * @param response servlet response
626     * @throws XServletException
627     */
628    private void changeCoordinatorJob(HttpServletRequest request, HttpServletResponse response)
629            throws XServletException {
630        CoordinatorEngine coordEngine = Services.get().get(CoordinatorEngineService.class).getCoordinatorEngine(
631                getUser(request));
632        String jobId = getResourceName(request);
633        String changeValue = request.getParameter(RestConstants.JOB_CHANGE_VALUE);
634        try {
635            coordEngine.change(jobId, changeValue);
636        }
637        catch (CoordinatorEngineException ex) {
638            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
639        }
640    }
641
642    /**
643     * Change a bundle job
644     *
645     * @param request servlet request
646     * @param response servlet response
647     * @throws XServletException
648     */
649    private void changeBundleJob(HttpServletRequest request, HttpServletResponse response)
650            throws XServletException {
651        BundleEngine bundleEngine = Services.get().get(BundleEngineService.class).getBundleEngine(getUser(request));
652        String jobId = getResourceName(request);
653        String changeValue = request.getParameter(RestConstants.JOB_CHANGE_VALUE);
654        try {
655            bundleEngine.change(jobId, changeValue);
656        }
657        catch (BundleEngineException ex) {
658            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
659        }
660    }
661
662    /**
663     * Rerun a wf job
664     *
665     * @param request servlet request
666     * @param response servlet response
667     * @param conf configuration object
668     * @throws XServletException
669     */
670    private void reRunWorkflowJob(HttpServletRequest request, HttpServletResponse response, Configuration conf)
671            throws XServletException {
672        DagEngine dagEngine = Services.get().get(DagEngineService.class).getDagEngine(getUser(request));
673
674        String jobId = getResourceName(request);
675        try {
676            dagEngine.reRun(jobId, conf);
677        }
678        catch (DagEngineException ex) {
679            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
680        }
681    }
682
683    /**
684     * Rerun bundle job
685     *
686     * @param request servlet request
687     * @param response servlet response
688     * @param conf configration object
689     * @throws XServletException
690     */
691    private void rerunBundleJob(HttpServletRequest request, HttpServletResponse response, Configuration conf)
692            throws XServletException {
693        JSONObject json = new JSONObject();
694        BundleEngine bundleEngine = Services.get().get(BundleEngineService.class).getBundleEngine(getUser(request));
695        String jobId = getResourceName(request);
696
697        String coordScope = request.getParameter(RestConstants.JOB_BUNDLE_RERUN_COORD_SCOPE_PARAM);
698        String dateScope = request.getParameter(RestConstants.JOB_BUNDLE_RERUN_DATE_SCOPE_PARAM);
699        String refresh = request.getParameter(RestConstants.JOB_COORD_RERUN_REFRESH_PARAM);
700        String noCleanup = request.getParameter(RestConstants.JOB_COORD_RERUN_NOCLEANUP_PARAM);
701
702        XLog.getLog(getClass()).info(
703                "Rerun Bundle for jobId=" + jobId + ", coordScope=" + coordScope + ", dateScope=" + dateScope + ", refresh="
704                        + refresh + ", noCleanup=" + noCleanup);
705
706        try {
707            bundleEngine.reRun(jobId, coordScope, dateScope, Boolean.valueOf(refresh), Boolean.valueOf(noCleanup));
708        }
709        catch (BaseEngineException ex) {
710            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
711        }
712    }
713
714    /**
715     * Rerun coordinator actions
716     *
717     * @param request servlet request
718     * @param response servlet response
719     * @param conf configuration object
720     * @throws XServletException
721     */
722    @SuppressWarnings("unchecked")
723    private JSONObject reRunCoordinatorActions(HttpServletRequest request, HttpServletResponse response,
724            Configuration conf) throws XServletException {
725        JSONObject json = new JSONObject();
726        CoordinatorEngine coordEngine = Services.get().get(CoordinatorEngineService.class).getCoordinatorEngine(getUser(request));
727
728        String jobId = getResourceName(request);
729
730        String rerunType = request.getParameter(RestConstants.JOB_COORD_RANGE_TYPE_PARAM);
731        String scope = request.getParameter(RestConstants.JOB_COORD_SCOPE_PARAM);
732        String refresh = request.getParameter(RestConstants.JOB_COORD_RERUN_REFRESH_PARAM);
733        String noCleanup = request.getParameter(RestConstants.JOB_COORD_RERUN_NOCLEANUP_PARAM);
734        String failed = request.getParameter(RestConstants.JOB_COORD_RERUN_FAILED_PARAM);
735
736        XLog.getLog(getClass()).info(
737                "Rerun coordinator for jobId=" + jobId + ", rerunType=" + rerunType + ",scope=" + scope + ",refresh="
738                        + refresh + ", noCleanup=" + noCleanup);
739
740        try {
741            if (!(rerunType.equals(RestConstants.JOB_COORD_SCOPE_DATE) || rerunType
742                    .equals(RestConstants.JOB_COORD_SCOPE_ACTION))) {
743                throw new CommandException(ErrorCode.E1018, "date or action expected.");
744            }
745            CoordinatorActionInfo coordInfo = coordEngine.reRun(jobId, rerunType, scope, Boolean.valueOf(refresh),
746                    Boolean.valueOf(noCleanup), Boolean.valueOf(failed), conf);
747            List<CoordinatorActionBean> coordActions;
748            if (coordInfo != null) {
749                coordActions = coordInfo.getCoordActions();
750            }
751            else {
752                coordActions = CoordUtils.getCoordActions(rerunType, jobId, scope, false);
753            }
754            json.put(JsonTags.COORDINATOR_ACTIONS, CoordinatorActionBean.toJSONArray(coordActions, "GMT"));
755        }
756        catch (BaseEngineException ex) {
757            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
758        }
759        catch (CommandException ex) {
760            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
761        }
762
763        return json;
764    }
765
766
767
768    /**
769     * Get workflow job
770     *
771     * @param request servlet request
772     * @param response servlet response
773     * @return JsonBean WorkflowJobBean
774     * @throws XServletException
775     */
776    protected JsonBean getWorkflowJob(HttpServletRequest request, HttpServletResponse response) throws XServletException {
777        JsonBean jobBean = getWorkflowJobBean(request, response);
778        // for backward compatibility (OOZIE-1231)
779        swapMRActionID((WorkflowJob)jobBean);
780        return jobBean;
781    }
782
783    /**
784     * Get workflow job
785     *
786     * @param request servlet request
787     * @param response servlet response
788     * @return JsonBean WorkflowJobBean
789     * @throws XServletException
790     */
791    protected JsonBean getWorkflowJobBean(HttpServletRequest request, HttpServletResponse response) throws XServletException {
792        JsonBean jobBean = null;
793        String jobId = getResourceName(request);
794        String startStr = request.getParameter(RestConstants.OFFSET_PARAM);
795        String lenStr = request.getParameter(RestConstants.LEN_PARAM);
796        int start = (startStr != null) ? Integer.parseInt(startStr) : 1;
797        start = (start < 1) ? 1 : start;
798        int len = (lenStr != null) ? Integer.parseInt(lenStr) : 0;
799        len = (len < 1) ? Integer.MAX_VALUE : len;
800        DagEngine dagEngine = Services.get().get(DagEngineService.class).getDagEngine(getUser(request));
801        try {
802            jobBean = (JsonBean) dagEngine.getJob(jobId, start, len);
803        }
804        catch (DagEngineException ex) {
805            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
806        }
807        return jobBean;
808    }
809
810    private void swapMRActionID(WorkflowJob wjBean) {
811        List<WorkflowAction> actions = wjBean.getActions();
812        if (actions != null) {
813            for (WorkflowAction wa : actions) {
814                swapMRActionID(wa);
815            }
816        }
817    }
818
819    private void swapMRActionID(WorkflowAction waBean) {
820        if (waBean.getType().equals("map-reduce")) {
821            String childId = waBean.getExternalChildIDs();
822            if (childId != null && !childId.equals("")) {
823                String consoleBase = getConsoleBase(waBean.getConsoleUrl());
824                ((WorkflowActionBean) waBean).setConsoleUrl(consoleBase + childId);
825                ((WorkflowActionBean) waBean).setExternalId(childId);
826                ((WorkflowActionBean) waBean).setExternalChildIDs("");
827            }
828        }
829    }
830
831    private String getConsoleBase(String url) {
832        String consoleBase = null;
833        if (url.indexOf("application") != -1) {
834            consoleBase = url.split("application_[0-9]+_[0-9]+")[0];
835        }
836        else {
837            consoleBase = url.split("job_[0-9]+_[0-9]+")[0];
838        }
839        return consoleBase;
840    }
841
842    /**
843     * Get wf action info
844     *
845     * @param request servlet request
846     * @param response servlet response
847     * @return JsonBean WorkflowActionBean
848     * @throws XServletException
849     */
850    protected JsonBean getWorkflowAction(HttpServletRequest request, HttpServletResponse response)
851            throws XServletException {
852
853        JsonBean actionBean = getWorkflowActionBean(request, response);
854        // for backward compatibility (OOZIE-1231)
855        swapMRActionID((WorkflowAction)actionBean);
856        return actionBean;
857    }
858
859    protected JsonBean getWorkflowActionBean(HttpServletRequest request, HttpServletResponse response)
860            throws XServletException {
861        DagEngine dagEngine = Services.get().get(DagEngineService.class).getDagEngine(getUser(request));
862
863        JsonBean actionBean = null;
864        String actionId = getResourceName(request);
865        try {
866            actionBean = dagEngine.getWorkflowAction(actionId);
867        }
868        catch (BaseEngineException ex) {
869            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
870        }
871        return actionBean;
872    }
873
874    /**
875     * Get coord job info
876     *
877     * @param request servlet request
878     * @param response servlet response
879     * @return JsonBean CoordinatorJobBean
880     * @throws XServletException
881     * @throws BaseEngineException
882     */
883    protected JsonBean getCoordinatorJob(HttpServletRequest request, HttpServletResponse response)
884            throws XServletException, BaseEngineException {
885        JsonBean jobBean = null;
886        CoordinatorEngine coordEngine = Services.get().get(CoordinatorEngineService.class).getCoordinatorEngine(
887                getUser(request));
888        String jobId = getResourceName(request);
889        String startStr = request.getParameter(RestConstants.OFFSET_PARAM);
890        String lenStr = request.getParameter(RestConstants.LEN_PARAM);
891        String filter = request.getParameter(RestConstants.JOB_FILTER_PARAM);
892        String orderStr = request.getParameter(RestConstants.ORDER_PARAM);
893        boolean order = (orderStr != null && orderStr.equals("desc")) ? true : false;
894        int offset = (startStr != null) ? Integer.parseInt(startStr) : 1;
895        offset = (offset < 1) ? 1 : offset;
896        // Get default number of coordinator actions to be retrieved
897        int defaultLen = ConfigurationService.getInt(COORD_ACTIONS_DEFAULT_LENGTH);
898        int len = (lenStr != null) ? Integer.parseInt(lenStr) : 0;
899        len = getCoordinatorJobLength(defaultLen, len);
900        try {
901            CoordinatorJobBean coordJob = coordEngine.getCoordJob(jobId, filter, offset, len, order);
902            jobBean = coordJob;
903        }
904        catch (CoordinatorEngineException ex) {
905            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
906        }
907
908        return jobBean;
909    }
910
911    /**
912     * Given the requested length and the default length, determine how many coordinator jobs to return.
913     * Used by {@link #getCoordinatorJob(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
914     *
915     * @param defaultLen The default length
916     * @param len The requested length
917     * @return The length to use
918     */
919    protected int getCoordinatorJobLength(int defaultLen, int len) {
920        return (len < 1) ? defaultLen : len;
921    }
922
923    /**
924     * Get bundle job info
925     *
926     * @param request servlet request
927     * @param response servlet response
928     * @return JsonBean bundle job bean
929     * @throws XServletException
930     * @throws BaseEngineException
931     */
932    private JsonBean getBundleJob(HttpServletRequest request, HttpServletResponse response) throws XServletException,
933            BaseEngineException {
934        JsonBean jobBean = null;
935        BundleEngine bundleEngine = Services.get().get(BundleEngineService.class).getBundleEngine(getUser(request));
936        String jobId = getResourceName(request);
937
938        try {
939            jobBean = (JsonBean) bundleEngine.getBundleJob(jobId);
940
941            return jobBean;
942        }
943        catch (BundleEngineException ex) {
944            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
945        }
946    }
947
948    /**
949     * Get coordinator action
950     *
951     * @param request servlet request
952     * @param response servlet response
953     * @return JsonBean CoordinatorActionBean
954     * @throws XServletException
955     * @throws BaseEngineException
956     */
957    private JsonBean getCoordinatorAction(HttpServletRequest request, HttpServletResponse response)
958            throws XServletException, BaseEngineException {
959        JsonBean actionBean = null;
960        CoordinatorEngine coordEngine = Services.get().get(CoordinatorEngineService.class).getCoordinatorEngine(
961                getUser(request));
962        String actionId = getResourceName(request);
963        try {
964            actionBean = coordEngine.getCoordAction(actionId);
965        }
966        catch (CoordinatorEngineException ex) {
967            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
968        }
969
970        return actionBean;
971    }
972
973    /**
974     * Get wf job definition
975     *
976     * @param request servlet request
977     * @param response servlet response
978     * @return String wf definition
979     * @throws XServletException
980     */
981    private String getWorkflowJobDefinition(HttpServletRequest request, HttpServletResponse response)
982            throws XServletException {
983        DagEngine dagEngine = Services.get().get(DagEngineService.class).getDagEngine(getUser(request));
984
985        String wfDefinition;
986        String jobId = getResourceName(request);
987        try {
988            wfDefinition = dagEngine.getDefinition(jobId);
989        }
990        catch (DagEngineException ex) {
991            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
992        }
993        return wfDefinition;
994    }
995
996    /**
997     * Get bundle job definition
998     *
999     * @param request servlet request
1000     * @param response servlet response
1001     * @return String bundle definition
1002     * @throws XServletException
1003     */
1004    private String getBundleJobDefinition(HttpServletRequest request, HttpServletResponse response) throws XServletException {
1005        BundleEngine bundleEngine = Services.get().get(BundleEngineService.class).getBundleEngine(getUser(request));
1006        String bundleDefinition;
1007        String jobId = getResourceName(request);
1008        try {
1009            bundleDefinition = bundleEngine.getDefinition(jobId);
1010        }
1011        catch (BundleEngineException ex) {
1012            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
1013        }
1014        return bundleDefinition;
1015    }
1016
1017    /**
1018     * Get coordinator job definition
1019     *
1020     * @param request servlet request
1021     * @param response servlet response
1022     * @return String coord definition
1023     * @throws XServletException
1024     */
1025    private String getCoordinatorJobDefinition(HttpServletRequest request, HttpServletResponse response)
1026            throws XServletException {
1027
1028        CoordinatorEngine coordEngine = Services.get().get(CoordinatorEngineService.class).getCoordinatorEngine(
1029                getUser(request));
1030
1031        String jobId = getResourceName(request);
1032
1033        String coordDefinition = null;
1034        try {
1035            coordDefinition = coordEngine.getDefinition(jobId);
1036        }
1037        catch (BaseEngineException ex) {
1038            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
1039        }
1040        return coordDefinition;
1041    }
1042
1043    /**
1044     * Stream wf job log
1045     *
1046     * @param request servlet request
1047     * @param response servlet response
1048     * @throws XServletException
1049     * @throws IOException
1050     */
1051    private void streamWorkflowJobLog(HttpServletRequest request, HttpServletResponse response)
1052            throws XServletException, IOException {
1053        DagEngine dagEngine = Services.get().get(DagEngineService.class).getDagEngine(getUser(request));
1054        String jobId = getResourceName(request);
1055        try {
1056            dagEngine.streamLog(jobId, response.getWriter(), request.getParameterMap());
1057        }
1058        catch (BaseEngineException ex) {
1059            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
1060        }
1061    }
1062
1063    /**
1064     * Stream bundle job log
1065     *
1066     * @param request servlet request
1067     * @param response servlet response
1068     * @throws XServletException
1069     */
1070    private void streamBundleJobLog(HttpServletRequest request, HttpServletResponse response)
1071            throws XServletException, IOException {
1072        BundleEngine bundleEngine = Services.get().get(BundleEngineService.class).getBundleEngine(getUser(request));
1073        String jobId = getResourceName(request);
1074        try {
1075            bundleEngine.streamLog(jobId, response.getWriter(), request.getParameterMap());
1076        }
1077        catch (BaseEngineException ex) {
1078            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
1079        }
1080    }
1081
1082    /**
1083     * Stream coordinator job log
1084     *
1085     * @param request servlet request
1086     * @param response servlet response
1087     * @throws XServletException
1088     * @throws IOException
1089     */
1090    private void streamCoordinatorJobLog(HttpServletRequest request, HttpServletResponse response)
1091            throws XServletException, IOException {
1092
1093        CoordinatorEngine coordEngine = Services.get().get(CoordinatorEngineService.class).getCoordinatorEngine(
1094                getUser(request));
1095        String jobId = getResourceName(request);
1096        String logRetrievalScope = request.getParameter(RestConstants.JOB_LOG_SCOPE_PARAM);
1097        String logRetrievalType = request.getParameter(RestConstants.JOB_LOG_TYPE_PARAM);
1098        try {
1099            coordEngine.streamLog(jobId, logRetrievalScope, logRetrievalType, response.getWriter(), request.getParameterMap());
1100        }
1101        catch (BaseEngineException ex) {
1102            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
1103        }
1104        catch (CommandException ex) {
1105            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
1106        }
1107    }
1108
1109    @Override
1110    protected String getJMSTopicName(HttpServletRequest request, HttpServletResponse response) throws XServletException,
1111            IOException {
1112        throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0302, NOT_SUPPORTED_MESSAGE);
1113    }
1114
1115    @Override
1116    protected JSONObject getJobsByParentId(HttpServletRequest request, HttpServletResponse response)
1117            throws XServletException, IOException {
1118        JSONObject json = new JSONObject();
1119        CoordinatorEngine coordEngine = Services.get().get(CoordinatorEngineService.class)
1120                .getCoordinatorEngine(getUser(request));
1121        String coordActionId;
1122        String type = request.getParameter(RestConstants.JOB_COORD_RANGE_TYPE_PARAM);
1123        String scope = request.getParameter(RestConstants.JOB_COORD_SCOPE_PARAM);
1124        // for getting allruns for coordinator action - 2 alternate endpoints
1125        if (type != null && type.equals(RestConstants.JOB_COORD_SCOPE_ACTION) && scope != null) {
1126            // endpoint - oozie/v2/coord-job-id?type=action&scope=action-num&show=allruns
1127            String jobId = getResourceName(request);
1128            coordActionId = Services.get().get(UUIDService.class).generateChildId(jobId, scope);
1129        }
1130        else {
1131            // endpoint - oozie/v2/coord-action-id?show=allruns
1132            coordActionId = getResourceName(request);
1133        }
1134        try {
1135            List<WorkflowJobBean> wfs = coordEngine.getReruns(coordActionId);
1136            JSONArray array = new JSONArray();
1137            if (wfs != null) {
1138                for (WorkflowJobBean wf : wfs) {
1139                    JSONObject json1 = new JSONObject();
1140                    json1.put(JsonTags.WORKFLOW_ID, wf.getId());
1141                    json1.put(JsonTags.WORKFLOW_STATUS, wf.getStatus().toString());
1142                    json1.put(JsonTags.WORKFLOW_START_TIME, JsonUtils.formatDateRfc822(wf.getStartTime(), "GMT"));
1143                    json1.put(JsonTags.WORKFLOW_ACTION_END_TIME, JsonUtils.formatDateRfc822(wf.getEndTime(), "GMT"));
1144                    array.add(json1);
1145                }
1146            }
1147            json.put(JsonTags.WORKFLOWS_JOBS, array);
1148            return json;
1149        }
1150        catch (CoordinatorEngineException ex) {
1151            throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
1152        }
1153    }
1154    /**
1155     * not supported for v1
1156     */
1157    @Override
1158    protected JSONObject updateJob(HttpServletRequest request, HttpServletResponse response, Configuration conf)
1159            throws XServletException, IOException {
1160        throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0302, NOT_SUPPORTED_MESSAGE);
1161    }
1162
1163    @Override
1164    protected String getJobStatus(HttpServletRequest request, HttpServletResponse response) throws XServletException,
1165            IOException {
1166        throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0302, NOT_SUPPORTED_MESSAGE);
1167    }
1168
1169    @Override
1170    protected void streamJobErrorLog(HttpServletRequest request, HttpServletResponse response) throws XServletException,
1171            IOException {
1172        throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0302, NOT_SUPPORTED_MESSAGE);
1173    }
1174    @Override
1175    protected void streamJobAuditLog(HttpServletRequest request, HttpServletResponse response) throws XServletException,
1176            IOException {
1177        throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0302, NOT_SUPPORTED_MESSAGE);
1178    }
1179    @Override
1180    void slaEnableAlert(HttpServletRequest request, HttpServletResponse response) throws XServletException, IOException {
1181        throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0302, NOT_SUPPORTED_MESSAGE);
1182    }
1183
1184    @Override
1185    void slaDisableAlert(HttpServletRequest request, HttpServletResponse response) throws XServletException,
1186            IOException {
1187        throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0302, NOT_SUPPORTED_MESSAGE);
1188    }
1189
1190    @Override
1191    void slaChange(HttpServletRequest request, HttpServletResponse response) throws XServletException, IOException {
1192        throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0302, NOT_SUPPORTED_MESSAGE);
1193    }
1194
1195    @Override
1196    JSONObject getCoordActionMissingDependencies(HttpServletRequest request, HttpServletResponse response)
1197            throws XServletException, IOException {
1198        throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0302, NOT_SUPPORTED_MESSAGE);
1199    }
1200
1201    @Override
1202    JSONArray getActionRetries(HttpServletRequest request, HttpServletResponse response) throws XServletException,
1203            IOException {
1204        throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0302, NOT_SUPPORTED_MESSAGE);
1205    }
1206}