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;
020
021import java.io.DataInput;
022import java.io.DataOutput;
023import java.io.IOException;
024import java.sql.Timestamp;
025import java.text.MessageFormat;
026import java.util.ArrayList;
027import java.util.Date;
028import java.util.List;
029
030import javax.persistence.Basic;
031import javax.persistence.Column;
032import javax.persistence.Entity;
033import javax.persistence.Id;
034import javax.persistence.Lob;
035import javax.persistence.NamedQueries;
036import javax.persistence.NamedQuery;
037import javax.persistence.Table;
038import javax.persistence.Transient;
039
040import org.apache.hadoop.io.Writable;
041import org.apache.oozie.client.BundleJob;
042import org.apache.oozie.client.CoordinatorJob;
043import org.apache.oozie.client.Job;
044import org.apache.oozie.client.rest.JsonBean;
045import org.apache.oozie.client.rest.JsonTags;
046import org.apache.oozie.client.rest.JsonUtils;
047import org.apache.oozie.util.DateUtils;
048import org.apache.oozie.util.WritableUtils;
049import org.apache.openjpa.persistence.jdbc.Index;
050import org.apache.openjpa.persistence.jdbc.Strategy;
051import org.json.simple.JSONArray;
052import org.json.simple.JSONObject;
053
054@Entity
055@NamedQueries( {
056        @NamedQuery(name = "UPDATE_BUNDLE_JOB", query = "update BundleJobBean w set w.appName = :appName, w.appPath = :appPath,"
057                + " w.conf = :conf, w.externalId = :externalId, w.timeOut = :timeOut, w.createdTimestamp = :createdTime,"
058                + " w.endTimestamp = :endTime, w.jobXml = :jobXml, w.lastModifiedTimestamp = :lastModifiedTime, w.origJobXml"
059                + " = :origJobXml, w.startTimestamp = :startTime, w.statusStr = :status, w.timeUnitStr = :timeUnit, w.pending"
060                + " = :pending where w.id = :id"),
061
062        @NamedQuery(name = "UPDATE_BUNDLE_JOB_STATUS", query = "update BundleJobBean w set w.statusStr = :status,"
063                + " w.lastModifiedTimestamp = :lastModifiedTime, w.pending = :pending where w.id = :id"),
064
065        @NamedQuery(name = "UPDATE_BUNDLE_JOB_STATUS_PENDING", query = "update BundleJobBean w set w.statusStr = :status,"
066                + " w.pending = :pending where w.id = :id"),
067
068        @NamedQuery(name = "UPDATE_BUNDLE_JOB_STATUS_PENDING_MODTIME", query = "update BundleJobBean w set w.statusStr = :status,"
069                + " w.lastModifiedTimestamp = :lastModifiedTime, w.pending = :pending where w.id = :id"),
070
071        @NamedQuery(name = "UPDATE_BUNDLE_JOB_STATUS_PENDING_SUSP_MOD_TIME", query = "update BundleJobBean w set w.statusStr "
072                + "= :status, w.lastModifiedTimestamp = :lastModifiedTime, w.pending = :pending, w.suspendedTimestamp "
073                + "= :suspendedTime where w.id = :id"),
074
075        @NamedQuery(name = "UPDATE_BUNDLE_JOB_STATUS_PAUSE_ENDTIME", query = "update BundleJobBean w set w.statusStr = :status,"
076                + " w.pauseTimestamp = :pauseTime, w.endTimestamp = :endTime where w.id = :id"),
077
078        @NamedQuery(name = "UPDATE_BUNDLE_JOB_PAUSE_KICKOFF", query = "update BundleJobBean w set w.kickoffTimestamp "
079                + "= :kickoffTime, w.pauseTimestamp = :pauseTime where w.id = :id"),
080
081        @NamedQuery(name = "DELETE_BUNDLE_JOB", query = "delete from BundleJobBean w where w.id IN (:id)"),
082
083        @NamedQuery(name = "GET_BUNDLE_JOBS", query = "select OBJECT(w) from BundleJobBean w"),
084
085        @NamedQuery(name = "GET_BUNDLE_JOB", query = "select OBJECT(w) from BundleJobBean w where w.id = :id"),
086
087        @NamedQuery(name = "GET_BUNDLE_JOB_STATUS", query = "select w.statusStr from BundleJobBean w where w.id = :id"),
088
089        @NamedQuery(name = "GET_BUNDLE_JOB_ID_STATUS_PENDING_MOD_PAUSE_SUSPEND_TIME", query = "select w.id, w.statusStr,"
090                + " w.pending, w.lastModifiedTimestamp, w.pauseTimestamp, w.suspendedTimestamp from BundleJobBean w where"
091                + " w.id = :id"),
092
093        @NamedQuery(name = "GET_BUNDLE_JOB_ID_JOBXML_CONF", query = "select w.id, w.jobXml, w.conf from BundleJobBean w"
094                + " where w.id = :id"),
095
096        @NamedQuery(name = "GET_BUNDLE_JOBS_COUNT", query = "select count(w) from BundleJobBean w"),
097
098        @NamedQuery(name = "GET_BUNDLE_JOBS_COLUMNS", query = "select w.id, w.appName, w.appPath, w.conf, w.statusStr,"
099                + " w.kickoffTimestamp, w.startTimestamp, w.endTimestamp, w.pauseTimestamp, w.createdTimestamp, w.user, w.group,"
100                + " w.timeUnitStr, w.timeOut from BundleJobBean w order by w.createdTimestamp desc"),
101
102        @NamedQuery(name = "GET_BUNDLE_JOBS_RUNNING_OR_PENDING", query = "select OBJECT(w) from BundleJobBean w where w.statusStr"
103                + " = 'RUNNING' OR w.statusStr = 'RUNNINGWITHERROR' OR w.pending = 1 order by w.lastModifiedTimestamp"),
104
105        @NamedQuery(name = "GET_BUNDLE_JOBS_NEED_START", query = "select OBJECT(w) from BundleJobBean w where w.statusStr "
106                + "= 'PREP' AND (w.kickoffTimestamp IS NULL OR (w.kickoffTimestamp IS NOT NULL AND w.kickoffTimestamp "
107                + "<= :currentTime)) order by w.lastModifiedTimestamp"),
108
109        @NamedQuery(name = "GET_BUNDLE_JOBS_PAUSED", query = "select OBJECT(w) from BundleJobBean w where w.statusStr = 'PAUSED'"
110                + " OR w.statusStr = 'PAUSEDWITHERROR' OR w.statusStr = 'PREPPAUSED' order by w.lastModifiedTimestamp"),
111
112        @NamedQuery(name = "GET_BUNDLE_JOBS_UNPAUSED", query = "select OBJECT(w) from BundleJobBean w where w.statusStr "
113                + "= 'RUNNING' OR w.statusStr = 'RUNNINGWITHERROR' OR w.statusStr = 'PREP' order by w.lastModifiedTimestamp"),
114
115        @NamedQuery(name = "GET_BUNDLE_JOBS_OLDER_THAN", query = "select OBJECT(w) from BundleJobBean w where w.startTimestamp "
116                + "<= :matTime AND (w.statusStr = 'PREP' OR w.statusStr = 'RUNNING' or w.statusStr = 'RUNNINGWITHERROR')  "
117                + "order by w.lastModifiedTimestamp"),
118
119        @NamedQuery(name = "GET_BUNDLE_JOBS_OLDER_THAN_STATUS", query = "select OBJECT(w) from BundleJobBean w where w.statusStr"
120                + " = :status AND w.lastModifiedTimestamp <= :lastModTime order by w.lastModifiedTimestamp"),
121
122        @NamedQuery(name = "GET_COMPLETED_BUNDLE_JOBS_OLDER_THAN", query = "select w.id from BundleJobBean w where ( w.statusStr"
123                + " = 'SUCCEEDED' OR w.statusStr = 'FAILED' OR w.statusStr = 'KILLED' OR w.statusStr = 'DONEWITHERROR') "
124                + "AND w.lastModifiedTimestamp <= :lastModTime order by w.lastModifiedTimestamp"),
125
126        @NamedQuery(name = "BULK_MONITOR_BUNDLE_QUERY", query = "SELECT b.id, b.appName, b.statusStr, b.user "
127                + "FROM BundleJobBean b"),
128
129        // Join query
130        @NamedQuery(name = "BULK_MONITOR_ACTIONS_QUERY", query = "SELECT a.id, a.actionNumber, a.errorCode, a.errorMessage,"
131                + " a.externalId, " +
132                "a.externalStatus, a.statusStr, a.createdTimestamp, a.nominalTimestamp, a.missingDependencies, " +
133                "c.id, c.appName, c.statusStr FROM CoordinatorActionBean a, CoordinatorJobBean c " +
134                "WHERE a.jobId = c.id AND c.bundleId = :bundleId ORDER BY a.jobId, a.createdTimestamp"),
135
136        @NamedQuery(name = "BULK_MONITOR_COUNT_QUERY", query = "SELECT COUNT(a) FROM CoordinatorActionBean a,"
137                + " CoordinatorJobBean c"),
138
139        @NamedQuery(name = "GET_BUNDLE_IDS_FOR_STATUS_TRANSIT", query = "select DISTINCT w.id from BundleActionBean a ,"
140                + " BundleJobBean w where a.lastModifiedTimestamp >= :lastModifiedTime and w.id = a.bundleId and (w.statusStr"
141                + " = 'RUNNING' OR w.statusStr = 'RUNNINGWITHERROR' OR w.statusStr = 'PAUSED' OR w.statusStr = 'PAUSEDWITHERROR'"
142                + " OR w.statusStr = 'SUSPENDED' OR w.statusStr = 'SUSPENDEDWITHERROR' OR w.pending = 1)"),
143
144
145        @NamedQuery(name = "GET_BUNDLE_JOB_FOR_USER", query = "select w.user from BundleJobBean w where w.id = :id") })
146@Table(name = "BUNDLE_JOBS")
147public class BundleJobBean implements Writable, BundleJob, JsonBean {
148
149    @Id
150    private String id;
151
152    @Basic
153    @Column(name = "app_path")
154    private String appPath = null;
155
156    @Basic
157    @Column(name = "app_name")
158    private String appName = null;
159
160    @Basic
161    @Column(name = "external_id")
162    private String externalId = null;
163
164    @Basic
165    @Column(name = "conf")
166    @Lob
167    @Strategy("org.apache.oozie.executor.jpa.StringBlobValueHandler")
168    private StringBlob conf;
169
170    @Basic
171    @Column(name = "time_out")
172    private int timeOut = 0;
173
174    @Basic
175    @Index
176    @Column(name = "user_name")
177    private String user = null;
178
179    @Basic
180    @Column(name = "group_name")
181    private String group = null;
182
183    @Transient
184    private String consoleUrl;
185
186    @Basic
187    @Index
188    @Column(name = "status")
189    private String statusStr = Job.Status.PREP.toString();
190
191    @Basic
192    @Column(name = "kickoff_time")
193    private java.sql.Timestamp kickoffTimestamp = null;
194
195    @Basic
196    @Column(name = "start_time")
197    private java.sql.Timestamp startTimestamp = null;
198
199    @Basic
200    @Index
201    @Column(name = "end_time")
202    private java.sql.Timestamp endTimestamp = null;
203
204    @Basic
205    @Column(name = "pause_time")
206    private java.sql.Timestamp pauseTimestamp = null;
207
208    @Basic
209    @Index
210    @Column(name = "created_time")
211    private java.sql.Timestamp createdTimestamp = null;
212
213    @Basic
214    @Column(name = "time_unit")
215    private String timeUnitStr = BundleJob.Timeunit.NONE.toString();
216
217    @Basic
218    @Column(name = "pending")
219    private int pending = 0;
220
221    @Basic
222    @Index
223    @Column(name = "last_modified_time")
224    private java.sql.Timestamp lastModifiedTimestamp = null;
225
226    @Basic
227    @Index
228    @Column(name = "suspended_time")
229    private java.sql.Timestamp suspendedTimestamp = null;
230
231    @Basic
232    @Column(name = "job_xml")
233    @Lob
234    @Strategy("org.apache.oozie.executor.jpa.StringBlobValueHandler")
235    private StringBlob jobXml;
236
237    @Basic
238    @Column(name = "orig_job_xml")
239    @Lob
240    @Strategy("org.apache.oozie.executor.jpa.StringBlobValueHandler")
241    private StringBlob origJobXml = null;
242
243
244    @Transient
245    private List<CoordinatorJobBean> coordJobs;
246
247    public BundleJobBean() {
248        coordJobs = new ArrayList<CoordinatorJobBean>();
249    }
250
251    /**
252     * @return the kickoffTimestamp
253     */
254    public java.sql.Timestamp getKickoffTimestamp() {
255        return kickoffTimestamp;
256    }
257
258    /**
259     * @return the startTimestamp
260     */
261    public java.sql.Timestamp getstartTimestamp() {
262        return startTimestamp;
263    }
264
265    /**
266     * @param kickoffTimestamp the kickoffTimestamp to set
267     */
268    public void setKickoffTimestamp(java.sql.Timestamp kickoffTimestamp) {
269        this.kickoffTimestamp = kickoffTimestamp;
270    }
271
272    /**
273     * @param startTimestamp the startTimestamp to set
274     */
275    public void setStartTimestamp(java.sql.Timestamp startTimestamp) {
276        this.startTimestamp = startTimestamp;
277    }
278
279    /**
280     * Set startTime
281     *
282     * @param startTime the startTime to set
283     */
284    public void setStartTime(Date startTime) {
285        this.startTimestamp = DateUtils.convertDateToTimestamp(startTime);
286    }
287
288    /**
289     * @return the endTimestamp
290     */
291    public java.sql.Timestamp getEndTimestamp() {
292        return endTimestamp;
293    }
294
295    /**
296     * @param endTimestamp the endTimestamp to set
297     */
298    public void setEndTimestamp(java.sql.Timestamp endTimestamp) {
299        this.endTimestamp = endTimestamp;
300    }
301
302    /**
303     * @return the pauseTimestamp
304     */
305    public java.sql.Timestamp getPauseTimestamp() {
306        return pauseTimestamp;
307    }
308
309    /**
310     * @param pauseTimestamp the pauseTimestamp to set
311     */
312    public void setPauseTimestamp(java.sql.Timestamp pauseTimestamp) {
313        this.pauseTimestamp = pauseTimestamp;
314    }
315
316    /**
317     * @return the createdTimestamp
318     */
319    public java.sql.Timestamp getCreatedTimestamp() {
320        return createdTimestamp;
321    }
322
323    /**
324     * @return the createdTime
325     */
326    @Override
327    public Date getCreatedTime() {
328        return DateUtils.toDate(createdTimestamp);
329    }
330
331    /**
332     * @return the timeUnitStr
333     */
334    public String getTimeUnitStr() {
335        return timeUnitStr;
336    }
337
338    /**
339     * @return the pending
340     */
341    public int getPending() {
342        return pending;
343    }
344
345    /**
346     * Set pending to true
347     */
348    @Override
349    public void setPending() {
350        this.pending = 1;
351    }
352
353    /**
354     * Set pending value
355     *
356     * @param pending set pending value
357     */
358    public void setPending(int pending) {
359        this.pending = pending;
360    }
361
362    /**
363     * Set pending to false
364     */
365    @Override
366    public void resetPending() {
367        this.pending = 0;
368    }
369
370    /**
371     * Return if the action is pending.
372     *
373     * @return if the action is pending.
374     */
375    public boolean isPending() {
376        return pending == 1 ? true : false;
377    }
378
379    /**
380     * @return the lastModifiedTimestamp
381     */
382    public java.sql.Timestamp getLastModifiedTimestamp() {
383        return lastModifiedTimestamp;
384    }
385
386    /**
387     * @param lastModifiedTimestamp the lastModifiedTimestamp to set
388     */
389    public void setLastModifiedTimestamp(java.sql.Timestamp lastModifiedTimestamp) {
390        this.lastModifiedTimestamp = lastModifiedTimestamp;
391    }
392
393    /**
394     * @return the suspendedTimestamp
395     */
396    public Timestamp getSuspendedTimestamp() {
397        return suspendedTimestamp;
398    }
399
400    /**
401     * @param suspendedTimestamp the suspendedTimestamp to set
402     */
403    public void setSuspendedTimestamp(Timestamp suspendedTimestamp) {
404        this.suspendedTimestamp = suspendedTimestamp;
405    }
406
407    /**
408     * @return the jobXml
409     */
410    public String getJobXml() {
411        return jobXml == null ? null : jobXml.getString();
412    }
413
414    /**
415     * @param jobXml the jobXml to set
416     */
417    public void setJobXml(String jobXml) {
418        if (this.jobXml == null) {
419            this.jobXml = new StringBlob(jobXml);
420        }
421        else {
422            this.jobXml.setString(jobXml);
423        }
424
425    }
426
427    public void setJobXmlBlob (StringBlob jobXmlBlob) {
428        this.jobXml = jobXmlBlob;
429    }
430
431    public StringBlob getJobXmlBlob() {
432        return jobXml;
433    }
434
435    /**
436     * @return the origJobXml
437     */
438    public String getOrigJobXml() {
439        return origJobXml == null ? null : origJobXml.getString();
440    }
441
442    /**
443     * @param origJobXml the origJobXml to set
444     */
445    public void setOrigJobXml(String origJobXml) {
446        if (this.origJobXml == null) {
447            this.origJobXml = new StringBlob(origJobXml);
448        }
449        else {
450            this.origJobXml.setString(origJobXml);
451        }
452    }
453
454    public void setOrigJobXmlBlob (StringBlob origJobXml) {
455        this.origJobXml = origJobXml;
456    }
457
458    public StringBlob getOrigJobXmlBlob() {
459        return origJobXml;
460    }
461
462    /**
463     * @param createTime the createdTime to set
464     */
465    public void setCreatedTime(Date createTime) {
466        this.createdTimestamp = DateUtils.convertDateToTimestamp(createTime);
467    }
468
469    /**
470     * @param lastModifiedTime the lastModifiedTime to set
471     */
472    public void setLastModifiedTime(Date lastModifiedTime) {
473        this.lastModifiedTimestamp = DateUtils.convertDateToTimestamp(lastModifiedTime);
474    }
475
476    /**
477     * Get last modified time
478     *
479     * @return last modified time
480     */
481    public Date getLastModifiedTime() {
482        return DateUtils.toDate(lastModifiedTimestamp);
483    }
484
485    @Override
486    public void write(DataOutput dataOutput) throws IOException {
487        WritableUtils.writeStr(dataOutput, getAppPath());
488        WritableUtils.writeStr(dataOutput, getAppName());
489        WritableUtils.writeStr(dataOutput, getId());
490        WritableUtils.writeStr(dataOutput, getConf());
491        WritableUtils.writeStr(dataOutput, getStatusStr());
492        WritableUtils.writeStr(dataOutput, getTimeUnit().toString());
493        dataOutput.writeLong((getKickoffTime() != null) ? getKickoffTime().getTime() : -1);
494        dataOutput.writeLong((getStartTime() != null) ? getStartTime().getTime() : -1);
495        dataOutput.writeLong((getEndTime() != null) ? getEndTime().getTime() : -1);
496        WritableUtils.writeStr(dataOutput, getUser());
497        WritableUtils.writeStr(dataOutput, getGroup());
498        WritableUtils.writeStr(dataOutput, getExternalId());
499        dataOutput.writeInt(getTimeout());
500    }
501
502    @Override
503    public void readFields(DataInput dataInput) throws IOException {
504
505        setAppPath(WritableUtils.readStr(dataInput));
506        setAppName(WritableUtils.readStr(dataInput));
507        setId(WritableUtils.readStr(dataInput));
508        setConf(WritableUtils.readStr(dataInput));
509        setStatus(BundleJob.Status.valueOf(WritableUtils.readStr(dataInput)));
510        setTimeUnit(BundleJob.Timeunit.valueOf(WritableUtils.readStr(dataInput)));
511
512        long d = dataInput.readLong();
513        if (d != -1) {
514            setKickoffTime(new Date(d));
515        }
516        d = dataInput.readLong();
517        if (d != -1) {
518            setStartTime(new Date(d));
519        }
520        d = dataInput.readLong();
521        if (d != -1) {
522            setEndTime(new Date(d));
523        }
524        setUser(WritableUtils.readStr(dataInput));
525        setGroup(WritableUtils.readStr(dataInput));
526        setExternalId(WritableUtils.readStr(dataInput));
527        setTimeOut(dataInput.readInt());
528    }
529
530
531    public Date getEndTime() {
532        return DateUtils.toDate(endTimestamp);
533    }
534
535    @Override
536    public Date getKickoffTime() {
537        return DateUtils.toDate(kickoffTimestamp);
538    }
539
540    @Override
541    public Timeunit getTimeUnit() {
542        return Timeunit.valueOf(this.timeUnitStr);
543    }
544
545    public void setEndTime(Date endTime) {
546        this.endTimestamp = DateUtils.convertDateToTimestamp(endTime);
547    }
548
549    public void setKickoffTime(Date kickoffTime) {
550        this.kickoffTimestamp = DateUtils.convertDateToTimestamp(kickoffTime);
551    }
552
553    @Override
554    public Date getPauseTime() {
555        return DateUtils.toDate(pauseTimestamp);
556    }
557
558    public void setPauseTime(Date pauseTime) {
559        this.pauseTimestamp = DateUtils.convertDateToTimestamp(pauseTime);
560    }
561
562    /**
563     * @param suspendTime the suspendTime
564     */
565    public void setSuspendedTime(Date suspendTime) {
566        this.suspendedTimestamp = DateUtils.convertDateToTimestamp(suspendTime);
567    }
568
569    @Override
570    @SuppressWarnings("unchecked")
571    public JSONObject toJSONObject() {
572        return toJSONObject("GMT");
573    }
574
575    @Override
576    @SuppressWarnings("unchecked")
577    public JSONObject toJSONObject(String timeZoneId) {
578        JSONObject json = new JSONObject();
579        json.put(JsonTags.BUNDLE_JOB_PATH, appPath);
580        json.put(JsonTags.BUNDLE_JOB_NAME, appName);
581        json.put(JsonTags.BUNDLE_JOB_ID, id);
582        json.put(JsonTags.BUNDLE_JOB_EXTERNAL_ID, externalId);
583        json.put(JsonTags.BUNDLE_JOB_CONF, getConf());
584        json.put(JsonTags.BUNDLE_JOB_STATUS, getStatus().toString());
585        json.put(JsonTags.BUNDLE_JOB_TIMEUNIT, getTimeUnit().toString());
586        json.put(JsonTags.BUNDLE_JOB_TIMEOUT, timeOut);
587        json.put(JsonTags.BUNDLE_JOB_KICKOFF_TIME, JsonUtils.formatDateRfc822(getKickoffTime(), timeZoneId));
588        json.put(JsonTags.BUNDLE_JOB_START_TIME, JsonUtils.formatDateRfc822(getStartTime(), timeZoneId));
589        json.put(JsonTags.BUNDLE_JOB_END_TIME, JsonUtils.formatDateRfc822(getEndTime(), timeZoneId));
590        json.put(JsonTags.BUNDLE_JOB_PAUSE_TIME, JsonUtils.formatDateRfc822(getPauseTime(), timeZoneId));
591        json.put(JsonTags.BUNDLE_JOB_CREATED_TIME, JsonUtils.formatDateRfc822(getCreatedTime(), timeZoneId));
592        json.put(JsonTags.BUNDLE_JOB_USER, getUser());
593        json.put(JsonTags.BUNDLE_JOB_GROUP, getGroup());
594        json.put(JsonTags.BUNDLE_JOB_ACL, getAcl());
595        json.put(JsonTags.BUNDLE_JOB_CONSOLE_URL, getConsoleUrl());
596        json.put(JsonTags.BUNDLE_COORDINATOR_JOBS, CoordinatorJobBean.toJSONArray(coordJobs, timeZoneId));
597        json.put(JsonTags.TO_STRING, toString());
598
599        return json;
600    }
601
602    @Override
603    public String getAppName() {
604        return appName;
605    }
606
607    @Override
608    public String getAppPath() {
609        return appPath;
610    }
611
612    @Override
613    public String getConf() {
614        return conf == null ? null : conf.getString();
615    }
616
617    @Override
618    public String getConsoleUrl() {
619        return consoleUrl;
620    }
621
622    @Override
623    @SuppressWarnings("unchecked")
624    public List<CoordinatorJob> getCoordinators() {
625        return (List) coordJobs;
626    }
627
628    @Override
629    @Deprecated
630    public String getGroup() {
631        return group;
632    }
633
634    @Override
635    public String getAcl() {
636        return getGroup();
637    }
638
639    @Override
640    public String getId() {
641        return id;
642    }
643
644    public int getTimeout() {
645        return timeOut;
646    }
647
648    public String getUser() {
649        return user;
650    }
651
652    /**
653     * Set id
654     *
655     * @param id the id to set
656     */
657    public void setId(String id) {
658        this.id = id;
659    }
660
661    /**
662     * Set bundlePath
663     *
664     * @param bundlePath the bundlePath to set
665     */
666    public void setAppPath(String bundlePath) {
667        this.appPath = bundlePath;
668    }
669
670    /**
671     * Set bundleName
672     *
673     * @param bundleName the bundleName to set
674     */
675    public void setAppName(String bundleName) {
676        this.appName = bundleName;
677    }
678
679    /**
680     * Return externalId
681     *
682     * @return externalId
683     */
684    public String getExternalId() {
685        return this.externalId;
686    }
687
688    /**
689     * Set externalId
690     *
691     * @param externalId the externalId to set
692     */
693    public void setExternalId(String externalId) {
694        this.externalId = externalId;
695    }
696
697    /**
698     * Set conf
699     *
700     * @param conf the conf to set
701     */
702    public void setConf(String conf) {
703        if (this.conf == null) {
704            this.conf = new StringBlob(conf);
705        }
706        else {
707            this.conf.setString(conf);
708        }
709    }
710
711    public void setConfBlob(StringBlob conf) {
712        this.conf = conf;
713    }
714
715    public StringBlob getConfBlob() {
716        return conf;
717    }
718
719    /**
720     * Set status
721     *
722     * @param status the status to set
723     */
724    public void setStatus(Status status) {
725        this.statusStr = status.toString();
726    }
727
728
729    @Override
730    public Status getStatus() {
731        return Status.valueOf(this.statusStr);
732    }
733
734    /**
735     * Set status
736     *
737     * @param statusStr the status to set
738     */
739    public void setStatus(String statusStr) {
740        this.statusStr = statusStr;
741    }
742
743
744    /**
745     * @return status string
746     */
747    public String getStatusStr() {
748        return statusStr;
749    }
750
751
752    /**
753     * Set timeUnit
754     *
755     * @param timeUnit the timeUnit to set
756     */
757    public void setTimeUnit(Timeunit timeUnit) {
758        this.timeUnitStr = timeUnit.toString();
759    }
760
761    /**
762     * Set timeOut
763     *
764     * @param timeOut the timeOut to set
765     */
766    public void setTimeOut(int timeOut) {
767        this.timeOut = timeOut;
768    }
769
770    /**
771     * Set user
772     *
773     * @param user the user to set
774     */
775    public void setUser(String user) {
776        this.user = user;
777    }
778
779    /**
780     * Set group
781     *
782     * @param group the group to set
783     */
784    public void setGroup(String group) {
785        this.group = group;
786    }
787
788    /**
789     * Set consoleUrl
790     *
791     * @param consoleUrl the consoleUrl to set
792     */
793    public void setConsoleUrl(String consoleUrl) {
794        this.consoleUrl = consoleUrl;
795    }
796
797    /**
798     * Set coordJobs
799     *
800     * @param coordJobs the coordJobs to set
801     */
802    public void setCoordJobs(List<CoordinatorJobBean> coordJobs) {
803        this.coordJobs = (coordJobs != null) ? coordJobs : new ArrayList<CoordinatorJobBean>();
804    }
805
806    /**
807     * Convert a Bundle job list into a JSONArray.
808     *
809     * @param applications list of applications.
810     * @param timeZoneId time zone to use for dates in the JSON array.
811     * @return the corresponding JSON array.
812     */
813    @SuppressWarnings("unchecked")
814    public static JSONArray toJSONArray(List<BundleJobBean> applications, String timeZoneId) {
815        JSONArray array = new JSONArray();
816        if (applications != null) {
817            for (BundleJobBean application : applications) {
818                array.add(application.toJSONObject(timeZoneId));
819            }
820        }
821        return array;
822    }
823
824
825    @Override
826    public String toString() {
827        return MessageFormat.format("Bundle id[{0}] status[{1}]", getId(), getStatus());
828    }
829
830    @Override
831    public Date getStartTime() {
832        return DateUtils.toDate(startTimestamp);
833    }
834
835    /**
836     * @return true if in terminal status
837     */
838    public boolean isTerminalStatus() {
839        boolean isTerminal = false;
840        switch (getStatus()) {
841            case SUCCEEDED:
842            case FAILED:
843            case KILLED:
844            case DONEWITHERROR:
845                isTerminal = true;
846                break;
847            default:
848                isTerminal = false;
849                break;
850        }
851        return isTerminal;
852    }
853}